Просмотр исходного кода

Merge branch 'BT21' of https://github.com/DCGO2/DCGO into bt21purple

dp101428 1 год назад
Родитель
Сommit
02294a9306
43 измененных файлов с 4397 добавлено и 92 удалено
  1. 1 1
      Assets/CardEffect/BT21/Black.meta
  2. 37 0
      Assets/CardEffect/BT21/Black/BT21_006.cs
  3. 11 0
      Assets/CardEffect/BT21/Black/BT21_006.cs.meta
  4. 212 0
      Assets/CardEffect/BT21/Black/BT21_053.cs
  5. 11 0
      Assets/CardEffect/BT21/Black/BT21_053.cs.meta
  6. 244 0
      Assets/CardEffect/BT21/Black/BT21_054.cs
  7. 11 0
      Assets/CardEffect/BT21/Black/BT21_054.cs.meta
  8. 120 0
      Assets/CardEffect/BT21/Black/BT21_055.cs
  9. 11 0
      Assets/CardEffect/BT21/Black/BT21_055.cs.meta
  10. 250 0
      Assets/CardEffect/BT21/Black/BT21_056.cs
  11. 11 0
      Assets/CardEffect/BT21/Black/BT21_056.cs.meta
  12. 392 0
      Assets/CardEffect/BT21/Black/BT21_057.cs
  13. 11 0
      Assets/CardEffect/BT21/Black/BT21_057.cs.meta
  14. 352 0
      Assets/CardEffect/BT21/Black/BT21_058.cs
  15. 11 0
      Assets/CardEffect/BT21/Black/BT21_058.cs.meta
  16. 243 0
      Assets/CardEffect/BT21/Black/BT21_059.cs
  17. 11 0
      Assets/CardEffect/BT21/Black/BT21_059.cs.meta
  18. 308 0
      Assets/CardEffect/BT21/Black/BT21_060.cs
  19. 11 0
      Assets/CardEffect/BT21/Black/BT21_060.cs.meta
  20. 303 0
      Assets/CardEffect/BT21/Black/BT21_061.cs
  21. 11 0
      Assets/CardEffect/BT21/Black/BT21_061.cs.meta
  22. 372 0
      Assets/CardEffect/BT21/Black/BT21_062.cs
  23. 11 0
      Assets/CardEffect/BT21/Black/BT21_062.cs.meta
  24. 132 0
      Assets/CardEffect/BT21/Black/BT21_087.cs
  25. 11 0
      Assets/CardEffect/BT21/Black/BT21_087.cs.meta
  26. 321 0
      Assets/CardEffect/BT21/Black/BT21_098.cs
  27. 11 0
      Assets/CardEffect/BT21/Black/BT21_098.cs.meta
  28. 382 0
      Assets/CardEffect/BT21/White/BT21_101.cs
  29. 11 0
      Assets/CardEffect/BT21/White/BT21_101.cs.meta
  30. 142 0
      Assets/CardEffect/BT21/White/BT21_102.cs
  31. 11 0
      Assets/CardEffect/BT21/White/BT21_102.cs.meta
  32. 0 1
      Assets/Editor/JSONLoader_CardEntity.cs
  33. 0 1
      Assets/Scripts/CEntity_Base.cs
  34. 0 7
      Assets/Scripts/CardEffectCommons/GameContextDeterminarion.cs
  35. 96 0
      Assets/Scripts/CardEffectFactory/AddLinkRequirement.cs
  36. 11 0
      Assets/Scripts/CardEffectFactory/AddLinkRequirement.cs.meta
  37. 3 3
      Assets/Scripts/CardEffectFactory/KeyWordEffects/Link.cs
  38. 7 0
      Assets/Scripts/CardEffectInterfaces.cs
  39. 27 0
      Assets/Scripts/CardEffects/AddLinkConditionClass.cs
  40. 11 0
      Assets/Scripts/CardEffects/AddLinkConditionClass.cs.meta
  41. 189 59
      Assets/Scripts/CardSource.cs
  42. 28 19
      Assets/Scripts/Effect Examples/Link_Examples.cs
  43. 49 1
      Assets/Scripts/TurnStateMachine.cs

+ 1 - 1
Assets/CardEffect/BT21/Black.meta

@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 9393f2d365d8275449dfc8c4c11a58c2
+guid: 22326d5e441baa44bb44fa428366e9fa
 folderAsset: yes
 DefaultImporter:
   externalObjects: {}

+ 37 - 0
Assets/CardEffect/BT21/Black/BT21_006.cs

@@ -0,0 +1,37 @@
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace DCGO.CardEffects.BT21
+{
+    //Tsumemon
+    public class BT21_006 : CEntity_Effect
+    {
+        public override List<ICardEffect> CardEffects(EffectTiming timing, CardSource card)
+        {
+            List<ICardEffect> cardEffects = new List<ICardEffect>();
+
+            #region Inherit
+            if (timing == EffectTiming.None)
+            {
+                bool VemmonCondition(CardSource source)
+                {
+                    return source.EqualsCardName("Vemmon");
+                }
+
+                bool Condition()
+                {
+                    if (CardEffectCommons.IsExistOnBattleAreaDigimon(card))
+                        return card.PermanentOfThisCard().DigivolutionCards.Count(VemmonCondition) >= 4;
+
+                    return false;
+                }
+
+                cardEffects.Add(CardEffectFactory.ChangeSelfDPStaticEffect(changeValue: 3000, isInheritedEffect: true, card: card, condition: Condition));
+            }
+            #endregion
+
+            return cardEffects;
+        }
+    }
+}

+ 11 - 0
Assets/CardEffect/BT21/Black/BT21_006.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f5522679b0f5b0845bc15d51789cffe1
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 212 - 0
Assets/CardEffect/BT21/Black/BT21_053.cs

@@ -0,0 +1,212 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace DCGO.CardEffects.BT21
+{
+    //Watchmon
+    public class BT21_053 : CEntity_Effect
+    {
+        public override List<ICardEffect> CardEffects(EffectTiming timing, CardSource card)
+        {
+            List<ICardEffect> cardEffects = new List<ICardEffect>();
+
+            #region Link Condition
+
+            if (timing == EffectTiming.None)
+            {
+                static bool PermanentCondition(Permanent targetPermanent)
+                {
+                    return targetPermanent.TopCard.HasAppmonTraits;
+                }
+
+                cardEffects.Add(CardEffectFactory.AddSelfLinkConditionStaticEffect(permanentCondition: PermanentCondition, linkCost: 0, card: card));
+            }
+
+            #endregion
+
+            #region Alternative Digivolution Condition
+
+            if (timing == EffectTiming.None)
+            {
+                bool PermanentCondition(Permanent targetPermanent)
+                {
+                    return targetPermanent.TopCard.IsLevel2 && targetPermanent.TopCard.EqualsTraits("Appmon");
+                }
+
+                cardEffects.Add(CardEffectFactory.AddSelfDigivolutionRequirementStaticEffect(
+                    permanentCondition: PermanentCondition,
+                    digivolutionCost: 0,
+                    ignoreDigivolutionRequirement: false,
+                    card: card,
+                    condition: null)
+                );
+            }
+
+            #endregion
+
+            #region On Play
+
+            if (timing == EffectTiming.OnEnterFieldAnyone)
+            {
+                ActivateClass activateClass = new ActivateClass();
+                activateClass.SetUpICardEffect("1 of your opponent's Digimon can't attack players until their turn ends", CanUseCondition, card);
+                activateClass.SetUpActivateClass(CanActivateCondition, ActivateCoroutine, -1, false, EffectDiscription());
+                cardEffects.Add(activateClass);
+
+                string EffectDiscription()
+                {
+                    return "[On Play] Until your opponent's turn ends, 1 of their Digimon can't attack players.";
+                }
+
+                bool IsOpponentsDigimon(Permanent permanent)
+                {
+                    return CardEffectCommons.IsPermanentExistsOnOpponentBattleAreaDigimon(permanent, card);
+                }
+
+                bool CanUseCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.IsExistOnBattleAreaDigimon(card) &&
+                        CardEffectCommons.CanTriggerOnPlay(hashtable, card) &&
+                        CardEffectCommons.HasMatchConditionOpponentsPermanent(card, IsOpponentsDigimon);
+                }
+
+                bool CanActivateCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.IsExistOnBattleAreaDigimon(card);
+                }
+
+                IEnumerator ActivateCoroutine(Hashtable hashtable)
+                {
+                    if (CardEffectCommons.HasMatchConditionPermanent(IsOpponentsDigimon))
+                    {
+                        int maxCount = Math.Min(1, CardEffectCommons.MatchConditionPermanentCount(IsOpponentsDigimon));
+
+                        SelectPermanentEffect selectPermanentEffect = GManager.instance.GetComponent<SelectPermanentEffect>();
+
+                        selectPermanentEffect.SetUp(
+                            selectPlayer: card.Owner,
+                            canTargetCondition: IsOpponentsDigimon,
+                            canTargetCondition_ByPreSelecetedList: null,
+                            canEndSelectCondition: null,
+                            maxCount: maxCount,
+                            canNoSelect: false,
+                            canEndNotMax: false,
+                            selectPermanentCoroutine: SelectCantAttackPermanent,
+                            afterSelectPermanentCoroutine: null,
+                            mode: SelectPermanentEffect.Mode.Custom,
+                            cardEffect: activateClass);
+
+                        yield return ContinuousController.instance.StartCoroutine(selectPermanentEffect.Activate());
+                    }
+
+                    IEnumerator SelectCantAttackPermanent(Permanent permanent)
+                    {
+                        bool DefenderCondition(Permanent Defender)
+                        {
+                            return Defender == null;
+                        }
+
+                        if (permanent != null)
+                        {
+                            yield return ContinuousController.instance.StartCoroutine(CardEffectCommons.GainCanNotAttack(
+                                targetPermanent: permanent,
+                                defenderCondition: DefenderCondition,
+                                effectDuration: EffectDuration.UntilOpponentTurnEnd,
+                                activateClass: activateClass,
+                                effectName: "Can't Attack Player"));
+                        }
+                    }
+                }
+            }
+            #endregion
+
+            #region Link
+            if (timing == EffectTiming.OnDeclaration)
+            {
+                cardEffects.Add(CardEffectFactory.LinkEffect(card));
+            }
+            #endregion
+
+            #region When Linking
+
+            if (timing == EffectTiming.WhenLinked)
+            {
+                ActivateClass activateClass = new ActivateClass();
+                activateClass.SetUpICardEffect("1 of your opponent's Digimon can't attack players until their turn ends", CanUseCondition, card);
+                activateClass.SetUpActivateClass(CanActivateCondition, ActivateCoroutine, -1, false, EffectDiscription());
+                activateClass.SetIsLinkedEffect(true);
+                cardEffects.Add(activateClass);
+
+                string EffectDiscription()
+                {
+                    return "[When Linking] Until your opponent's turn ends, 1 of their Digimon can't attack players.";
+                }
+
+                bool IsOpponentsDigimon(Permanent permanent)
+                {
+                    return CardEffectCommons.IsPermanentExistsOnOpponentBattleAreaDigimon(permanent, card);
+                }
+
+                bool CanUseCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.IsExistOnBattleAreaDigimon(card) &&
+                        CardEffectCommons.CanTriggerWhenLinking(hashtable, null, card) &&
+                        CardEffectCommons.HasMatchConditionOpponentsPermanent(card, IsOpponentsDigimon);
+                }
+
+                bool CanActivateCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.IsExistOnBattleAreaDigimon(card);
+                }
+
+                IEnumerator ActivateCoroutine(Hashtable hashtable)
+                {
+                    if (CardEffectCommons.HasMatchConditionPermanent(IsOpponentsDigimon))
+                    {
+                        int maxCount = Math.Min(1, CardEffectCommons.MatchConditionPermanentCount(IsOpponentsDigimon));
+
+                        SelectPermanentEffect selectPermanentEffect = GManager.instance.GetComponent<SelectPermanentEffect>();
+
+                        selectPermanentEffect.SetUp(
+                            selectPlayer: card.Owner,
+                            canTargetCondition: IsOpponentsDigimon,
+                            canTargetCondition_ByPreSelecetedList: null,
+                            canEndSelectCondition: null,
+                            maxCount: maxCount,
+                            canNoSelect: false,
+                            canEndNotMax: false,
+                            selectPermanentCoroutine: SelectCantAttackPermanent,
+                            afterSelectPermanentCoroutine: null,
+                            mode: SelectPermanentEffect.Mode.Custom,
+                            cardEffect: activateClass);
+
+                        yield return ContinuousController.instance.StartCoroutine(selectPermanentEffect.Activate());
+                    }
+
+                    IEnumerator SelectCantAttackPermanent(Permanent permanent)
+                    {
+                        bool DefenderCondition(Permanent Defender)
+                        {
+                            return Defender == null;
+                        }
+
+                        if (permanent != null)
+                        {
+                            yield return ContinuousController.instance.StartCoroutine(CardEffectCommons.GainCanNotAttack(
+                                targetPermanent: permanent,
+                                defenderCondition: DefenderCondition,
+                                effectDuration: EffectDuration.UntilOpponentTurnEnd,
+                                activateClass: activateClass,
+                                effectName: "Can't Attack Player"));
+                        }
+                    }
+                }
+            }
+
+            #endregion
+
+            return cardEffects;
+        }
+    }
+}

+ 11 - 0
Assets/CardEffect/BT21/Black/BT21_053.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: dea65eff6aa0c014abfdec0d741814db
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 244 - 0
Assets/CardEffect/BT21/Black/BT21_054.cs

@@ -0,0 +1,244 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace DCGO.CardEffects.BT21
+{
+    //Shotmon
+    public class BT21_054 : CEntity_Effect
+    {
+        public override List<ICardEffect> CardEffects(EffectTiming timing, CardSource card)
+        {
+            List<ICardEffect> cardEffects = new List<ICardEffect>();
+
+            int totalSourceCount = 0;
+
+            #region Link Condition
+
+            if (timing == EffectTiming.None)
+            {
+                static bool PermanentCondition(Permanent targetPermanent)
+                {
+                    return targetPermanent.TopCard.HasAppmonTraits;
+                }
+
+                cardEffects.Add(CardEffectFactory.AddSelfLinkConditionStaticEffect(permanentCondition: PermanentCondition, linkCost: 0, card: card));
+            }
+
+            #endregion
+
+            #region Alternative Digivolution Condition
+
+            if (timing == EffectTiming.None)
+            {
+                bool PermanentCondition(Permanent targetPermanent)
+                {
+                    return targetPermanent.TopCard.IsLevel2 && (targetPermanent.TopCard.EqualsTraits("Appmon") || targetPermanent.TopCard.HasText("Three Musketeers"));
+                }
+
+                cardEffects.Add(CardEffectFactory.AddSelfDigivolutionRequirementStaticEffect(
+                    permanentCondition: PermanentCondition,
+                    digivolutionCost: 0,
+                    ignoreDigivolutionRequirement: false,
+                    card: card,
+                    condition: null)
+                );
+            }
+
+            #endregion
+
+            #region On Play
+
+            if (timing == EffectTiming.OnEnterFieldAnyone)
+            {
+                ActivateClass activateClass = new ActivateClass();
+                activateClass.SetUpICardEffect("Trash 1 source and de-digivolve 1.", CanUseCondition, card);
+                activateClass.SetUpActivateClass(CanActivateCondition, ActivateCoroutine, -1, true, EffectDescription());
+                cardEffects.Add(activateClass);
+
+                string EffectDescription()
+                {
+                    return "[On Play] By trashing 1 card with the [Appmon] or [Three Musketeers] trait from any of your Digimon's digivolution cards, <De-Digivolve 1> 1 of your opponent's Digimon.";
+                }
+
+                bool HasProperTrait(CardSource source)
+                {
+                    return !source.CanNotTrashFromDigivolutionCards(activateClass) &&
+                        source.EqualsTraits("Appmon") || source.EqualsTraits("Three Musketeers");
+                }
+
+                bool CanSelectTrashTargetCondition(Permanent permanent)
+                {
+                    if (CardEffectCommons.IsPermanentExistsOnOwnerBattleAreaDigimon(permanent, card))
+                    {
+                        totalSourceCount = permanent.DigivolutionCards.Count(HasProperTrait);
+                        
+                        if (totalSourceCount >= 1)
+                        {
+                            return true;
+                        }
+                    }
+
+                    return false;
+                }
+
+                bool CanSelectPermanentCondition(Permanent permanent)
+                {
+                    return CardEffectCommons.IsPermanentExistsOnOpponentBattleAreaDigimon(permanent, card);
+                }
+
+                bool CanUseCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.CanTriggerOnPlay(hashtable, card);
+                }
+
+                bool CanActivateCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.IsExistOnBattleAreaDigimon(card) &&
+                        CardEffectCommons.HasMatchConditionPermanent(CanSelectTrashTargetCondition) &&
+                        totalSourceCount >= 1;
+                }
+
+                IEnumerator ActivateCoroutine(Hashtable hashtable)
+                {
+                    bool cardsTrashed = false;
+                    Permanent selectedPermanent = null;
+
+                    yield return ContinuousController.instance.StartCoroutine(CardEffectCommons.SelectTrashDigivolutionCards(
+                        permanentCondition: CanSelectTrashTargetCondition,
+                        cardCondition: HasProperTrait,
+                        maxCount: 1,
+                        canNoTrash: false,
+                        isFromOnly1Permanent: false,
+                        activateClass: activateClass,
+                        afterSelectionCoroutine: AfterTrashedCards
+                    ));
+
+                    IEnumerator AfterTrashedCards(Permanent permanent, List<CardSource> cards)
+                    {
+                        if (cards.Count == 1)
+                            cardsTrashed = true;
+
+                        selectedPermanent = permanent;
+
+                        yield return null;
+                    }
+
+                    if (cardsTrashed && CardEffectCommons.HasMatchConditionPermanent(CanSelectPermanentCondition))
+                    {
+                        int maxCount = Math.Min(1, CardEffectCommons.MatchConditionPermanentCount(CanSelectPermanentCondition));
+
+                        SelectPermanentEffect selectPermanentEffect = GManager.instance.GetComponent<SelectPermanentEffect>();
+
+                        selectPermanentEffect.SetUp(
+                            selectPlayer: card.Owner,
+                            canTargetCondition: CanSelectPermanentCondition,
+                            canTargetCondition_ByPreSelecetedList: null,
+                            canEndSelectCondition: CanEndSelectCondition,
+                            maxCount: maxCount,
+                            canNoSelect: false,
+                            canEndNotMax: false,
+                            selectPermanentCoroutine: SelectPermanentCoroutine,
+                            afterSelectPermanentCoroutine: null,
+                            mode: SelectPermanentEffect.Mode.Custom,
+                            cardEffect: activateClass);
+
+                        selectPermanentEffect.SetUpCustomMessage("Select 1 Digimon to De-Digivolve.", "The opponent is selecting 1 Digimon to De-Digivolve.");
+
+                        yield return ContinuousController.instance.StartCoroutine(selectPermanentEffect.Activate());
+
+                        bool CanEndSelectCondition(List<Permanent> permanents)
+                        {
+                            return permanents.Count > 0;
+                        }
+
+                        IEnumerator SelectPermanentCoroutine(Permanent permanent)
+                        {
+                            Permanent selectedPermanent = permanent;
+
+                            if (selectedPermanent != null)
+                            {
+                                yield return ContinuousController.instance.StartCoroutine(new IDegeneration(selectedPermanent, 1, activateClass).Degeneration());
+                            }
+
+                            yield return null;
+                        }
+                    }
+                }
+            }
+
+            #endregion
+
+            #region Link
+            if (timing == EffectTiming.OnDeclaration)
+            {
+                cardEffects.Add(CardEffectFactory.LinkEffect(card));
+            }
+            #endregion
+
+            #region When Linking
+
+            if (timing == EffectTiming.WhenLinked)
+            {
+                ActivateClass activateClass = new ActivateClass();
+                activateClass.SetUpICardEffect("Delete 1 Digimon with 3 or less Cost", CanUseCondition, card);
+                activateClass.SetUpActivateClass(CanActivateCondition, ActivateCoroutine, -1, false, EffectDiscription());
+                activateClass.SetIsLinkedEffect(true);
+                cardEffects.Add(activateClass);
+
+                string EffectDiscription()
+                {
+                    return "[When Linking] Delete 1 of your opponent's Digimon with a play cost of 3 or less.";
+                }
+
+                bool CanSelectPermanentCondition(Permanent permanent)
+                {
+                    return CardEffectCommons.IsPermanentExistsOnOpponentBattleAreaDigimon(permanent, card) &&
+                        permanent.TopCard.HasPlayCost &&
+                        permanent.TopCard.GetCostItself <= 3;
+                }
+
+                bool CanUseCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.CanTriggerWhenLinking(hashtable, null, card);
+                }
+
+                bool CanActivateCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.IsExistOnBattleAreaDigimon(card) &&
+                        CardEffectCommons.HasMatchConditionPermanent(CanSelectPermanentCondition);
+                }
+
+                IEnumerator ActivateCoroutine(Hashtable hashtable)
+                {
+                    if (CardEffectCommons.HasMatchConditionPermanent(CanSelectPermanentCondition))
+                    {
+                        int maxCount = Math.Min(1, CardEffectCommons.MatchConditionPermanentCount(CanSelectPermanentCondition));
+
+                        SelectPermanentEffect selectPermanentEffect = GManager.instance.GetComponent<SelectPermanentEffect>();
+
+                        selectPermanentEffect.SetUp(
+                            selectPlayer: card.Owner,
+                            canTargetCondition: CanSelectPermanentCondition,
+                            canTargetCondition_ByPreSelecetedList: null,
+                            canEndSelectCondition: null,
+                            maxCount: maxCount,
+                            canNoSelect: false,
+                            canEndNotMax: false,
+                            selectPermanentCoroutine: null,
+                            afterSelectPermanentCoroutine: null,
+                            mode: SelectPermanentEffect.Mode.Destroy,
+                            cardEffect: activateClass);
+
+                        yield return ContinuousController.instance.StartCoroutine(selectPermanentEffect.Activate());
+                    }
+                }
+            }
+
+            #endregion
+
+            return cardEffects;
+        }
+    }
+}

+ 11 - 0
Assets/CardEffect/BT21/Black/BT21_054.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: e451a7c628a1682469a24ea227ce85a9
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 120 - 0
Assets/CardEffect/BT21/Black/BT21_055.cs

@@ -0,0 +1,120 @@
+using System.Collections;
+using System.Collections.Generic;
+
+namespace DCGO.CardEffects.BT21
+{
+    //Sunarizamon
+    public class BT21_055 : CEntity_Effect
+    {
+        public override List<ICardEffect> CardEffects(EffectTiming timing, CardSource card)
+        {
+            List<ICardEffect> cardEffects = new List<ICardEffect>();
+
+            #region Your Turn
+            if (timing == EffectTiming.None)
+            {
+                bool Condition()
+                {
+                    return CardEffectCommons.IsOwnerTurn(card) && CardEffectCommons.IsExistOnBattleArea(card);
+                }
+
+                bool PermanentCondition(Permanent targetPermanent)
+                {
+                    return targetPermanent == card.PermanentOfThisCard();
+                }
+
+                bool CardSourceCondition(CardSource cardSource)
+                {
+                    if (cardSource.EqualsTraits("Mineral") | cardSource.EqualsTraits("Rock"))
+                    {
+                        return true;
+                    }
+
+                    return false;
+                }
+
+                bool RootCondition(SelectCardEffect.Root root)
+                {
+                    return true;
+                }
+
+                cardEffects.Add(CardEffectFactory.ChangeDigivolutionCostStaticEffect(
+                    changeValue: -1,
+                    permanentCondition: PermanentCondition,
+                    cardCondition: CardSourceCondition,
+                    rootCondition: RootCondition,
+                    isInheritedEffect: false,
+                    card: card,
+                    condition: Condition,
+                    setFixedCost: false));
+            }
+            #endregion
+
+            #region Inherited
+            if (timing == EffectTiming.OnDigivolutionCardDiscarded)
+            {
+                ActivateClass activateClass = new ActivateClass();
+                activateClass.SetUpICardEffect("Delete 4 cost or less Digimon", CanUseCondition, card);
+                activateClass.SetUpActivateClass(CanActivateCondition, ActivateCoroutine, -1, false, EffectDiscription());
+                activateClass.SetIsInheritedEffect(true);
+                cardEffects.Add(activateClass);
+
+                string EffectDiscription()
+                {
+                    return "When effects trash this card from a [Mineral] or [Rock] trait Digimon's digivolution cards, delete 1 of your opponent's Digimon with a play cost of 4 or less.";
+                }
+
+                bool CanSelectOpponentsDigimon(Permanent permanent)
+                {
+                    if (CardEffectCommons.IsPermanentExistsOnOpponentBattleAreaDigimon(permanent, card))
+                        return permanent.TopCard.HasPlayCost && permanent.TopCard.GetCostItself <= 4;
+
+                    return false;
+                }
+
+                bool CanUseCondition(Hashtable hashtable)
+                {
+                    Permanent trashedPermanent = CardEffectCommons.GetPermanentFromHashtable(hashtable);
+                    return (trashedPermanent.TopCard.EqualsTraits("Mineral") || trashedPermanent.TopCard.EqualsTraits("Rock")) &&
+                           CardEffectCommons.CanTriggerOnTrashSelfDigivolutionCard(hashtable, cardEffect => cardEffect != null, card);
+                }
+
+                bool CanActivateCondition(Hashtable hashtable)
+                {
+                    if (CardEffectCommons.IsExistOnTrash(card))
+                    {
+                        if (CardEffectCommons.HasMatchConditionOpponentsPermanent(card, CanSelectOpponentsDigimon))
+                        {
+                            return true;
+                        }
+                    }
+
+                    return false;
+                }
+
+                IEnumerator ActivateCoroutine(Hashtable hashtable)
+                {
+                    SelectPermanentEffect selectPermanentEffect = GManager.instance.GetComponent<SelectPermanentEffect>();
+
+                    selectPermanentEffect.SetUp(
+                        selectPlayer: card.Owner,
+                        canTargetCondition: CanSelectOpponentsDigimon,
+                        canTargetCondition_ByPreSelecetedList: null,
+                        canEndSelectCondition: null,
+                        maxCount: 1,
+                        canNoSelect: true,
+                        canEndNotMax: false,
+                        selectPermanentCoroutine: null,
+                        afterSelectPermanentCoroutine: null,
+                        mode: SelectPermanentEffect.Mode.Destroy,
+                        cardEffect: activateClass);
+
+                    yield return ContinuousController.instance.StartCoroutine(selectPermanentEffect.Activate());
+                }
+            }
+            #endregion
+
+            return cardEffects;
+        }
+    }
+}

+ 11 - 0
Assets/CardEffect/BT21/Black/BT21_055.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: ccdc42c2c270473458d556c41592a53d
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 250 - 0
Assets/CardEffect/BT21/Black/BT21_056.cs

@@ -0,0 +1,250 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace DCGO.CardEffects.BT21
+{
+    //Vemmon
+    public class BT21_056 : CEntity_Effect
+    {
+        public override List<ICardEffect> CardEffects(EffectTiming timing, CardSource card)
+        {
+            List<ICardEffect> cardEffects = new List<ICardEffect>();
+
+            #region On Play
+
+            if (timing == EffectTiming.OnEnterFieldAnyone)
+            {
+                ActivateClass activateClass = new ActivateClass();
+                activateClass.SetUpICardEffect("Trash 1 card with [Vemmon] in text from hand to return 1 non-Digi-Egg card with [Vemmon] in text from trash to hand", CanUseCondition, card);
+                activateClass.SetUpActivateClass(CanActivateCondition, ActivateCoroutine, -1, true, EffectDiscription());
+                cardEffects.Add(activateClass);
+
+                string EffectDiscription()
+                {
+                    return "[On Play] By trashing 1 card with [Vemmon] in its text from your hand, you may return 1 non-Digi-Egg card with [Vemmon] in its text from your trash to the hand.";
+                }
+
+                bool CanSelectCardCondition(CardSource cardSource)
+                {
+                    if (cardSource != null)
+                    {
+                        if (cardSource.Owner == card.Owner)
+                        {
+                            if (cardSource.HasText("Vemmon") && !cardSource.IsDigiEgg)
+                            {
+                                return true;
+                            }
+                        }
+                    }
+
+                    return false;
+                }
+
+                bool CanUseCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.CanTriggerOnPlay(hashtable, card);
+                }
+
+                bool CanActivateCondition(Hashtable hashtable)
+                {
+                    if (CardEffectCommons.IsExistOnBattleArea(card))
+                    {
+                        if (card.Owner.HandCards.Count >= 1)
+                        {
+                            return true;
+                        }
+                    }
+
+                    return false;
+                }
+
+                IEnumerator ActivateCoroutine(Hashtable hashtable)
+                {
+                    if (isExistOnField(card))
+                    {
+                        if (card.Owner.GetBattleAreaDigimons().Contains(card.PermanentOfThisCard()))
+                        {
+                            if (card.Owner.HandCards.Count(CanSelectCardCondition) >= 1)
+                            {
+                                bool discarded = false;
+
+                                int discardCount = 1;
+
+                                SelectHandEffect selectHandEffect = GManager.instance.GetComponent<SelectHandEffect>();
+
+                                selectHandEffect.SetUp(
+                                    selectPlayer: card.Owner,
+                                    canTargetCondition: CanSelectCardCondition,
+                                    canTargetCondition_ByPreSelecetedList: null,
+                                    canEndSelectCondition: null,
+                                    maxCount: discardCount,
+                                    canNoSelect: true,
+                                    canEndNotMax: false,
+                                    isShowOpponent: true,
+                                    selectCardCoroutine: null,
+                                    afterSelectCardCoroutine: AfterSelectCardCoroutine,
+                                    mode: SelectHandEffect.Mode.Discard,
+                                    cardEffect: activateClass);
+
+                                yield return StartCoroutine(selectHandEffect.Activate());
+
+                                IEnumerator AfterSelectCardCoroutine(List<CardSource> cardSources)
+                                {
+                                    if (cardSources.Count >= 1)
+                                    {
+                                        discarded = true;
+
+                                        yield return null;
+                                    }
+                                }
+
+                                if (discarded)
+                                {
+                                    if (CardEffectCommons.HasMatchConditionOwnersCardInTrash(card, CanSelectCardCondition))
+                                    {
+                                        int maxCount = Math.Min(1, card.Owner.TrashCards.Count(CanSelectCardCondition));
+
+                                        SelectCardEffect selectCardEffect = GManager.instance.GetComponent<SelectCardEffect>();
+
+                                        selectCardEffect.SetUp(
+                                            canTargetCondition: CanSelectCardCondition,
+                                            canTargetCondition_ByPreSelecetedList: null,
+                                            canEndSelectCondition: null,
+                                            canNoSelect: () => false,
+                                            selectCardCoroutine: null,
+                                            afterSelectCardCoroutine: null,
+                                            message: "Select 1 card to add to your hand.",
+                                            maxCount: maxCount,
+                                            canEndNotMax: false,
+                                            isShowOpponent: true,
+                                            mode: SelectCardEffect.Mode.AddHand,
+                                            root: SelectCardEffect.Root.Trash,
+                                            customRootCardList: null,
+                                            canLookReverseCard: true,
+                                            selectPlayer: card.Owner,
+                                            cardEffect: activateClass);
+
+                                        yield return ContinuousController.instance.StartCoroutine(selectCardEffect.Activate());
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+            #endregion
+
+            #region Your Turn Inherited
+
+            if (timing == EffectTiming.BeforePayCost)
+            {
+                ActivateClass activateClass = new ActivateClass();
+                activateClass.SetUpICardEffect("Digivolution Cost -1", CanUseCondition, card);
+                activateClass.SetUpActivateClass(CanActivateCondition, ActivateCoroutine, 1, false, EffectDiscription());
+                activateClass.SetIsInheritedEffect(true);
+                activateClass.SetHashString("DigivolutionCost-1_BT21_056");
+                cardEffects.Add(activateClass);
+
+                string EffectDiscription()
+                {
+                    return "[Your Turn] [Once Per Turn] When this Digimon would digivolve into a Digimon card with [Vemmon] in its text, reduce the digivolution cost by 1.";
+                }
+
+                bool PermanentCondition(Permanent permanent)
+                {
+                    return CardEffectCommons.IsPermanentExistsOnOwnerBattleAreaDigimon(permanent, card) &&
+                        permanent == card.PermanentOfThisCard();
+                }
+
+                bool CardCondition(CardSource cardSource)
+                {
+                    return cardSource.IsDigimon &&
+                        cardSource.HasText("Vemmon");
+                }
+
+                bool CanUseCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.IsExistOnBattleAreaDigimon(card) &&
+                        CardEffectCommons.IsOwnerTurn(card) &&
+                        CardEffectCommons.CanTriggerWhenPermanentWouldDigivolve(hashtable, PermanentCondition, CardCondition);
+                }
+
+                bool CanActivateCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.IsExistOnBattleAreaDigimon(card);
+                }
+
+                IEnumerator ActivateCoroutine(Hashtable _hashtable)
+                {
+                    if (isExistOnField(card))
+                    {
+                        Hashtable hashtable = new Hashtable();
+                        hashtable.Add("CardEffect", activateClass);
+
+                        ContinuousController.instance.PlaySE(GManager.instance.GetComponent<Effects>().BuffSE);
+
+                        ChangeCostClass changeCostClass = new ChangeCostClass();
+                        changeCostClass.SetUpICardEffect("Digivolution Cost -1", CanUseCondition1, card);
+                        changeCostClass.SetUpChangeCostClass(changeCostFunc: ChangeCost, cardSourceCondition: CardSourceCondition, rootCondition: RootCondition, isUpDown: isUpDown, isCheckAvailability: () => false, isChangePayingCost: () => true);
+                        card.Owner.UntilCalculateFixedCostEffect.Add((_timing) => changeCostClass);
+
+                        yield return ContinuousController.instance.StartCoroutine(CardEffectCommons.ShowReducedCost(_hashtable));
+
+                        bool CanUseCondition1(Hashtable hashtable)
+                        {
+                            return true;
+                        }
+
+                        int ChangeCost(CardSource cardSource, int Cost, SelectCardEffect.Root root, List<Permanent> targetPermanents)
+                        {
+                            if (CardSourceCondition(cardSource) && RootCondition(root) && PermanentsCondition(targetPermanents))
+                            {
+                                Cost -= 1;
+                            }
+
+                            return Cost;
+                        }
+
+                        bool PermanentsCondition(List<Permanent> targetPermanents)
+                        {
+                            return targetPermanents != null &&
+                                targetPermanents.Count(PermanentCondition) >= 1;
+                        }
+
+                        bool PermanentCondition(Permanent targetPermanent)
+                        {
+                            return targetPermanent.TopCard != null &&
+                                targetPermanent.TopCard.Owner == card.Owner &&
+                                targetPermanent.TopCard.Owner.GetBattleAreaPermanents().Contains(targetPermanent);
+                        }
+
+                        bool CardSourceCondition(CardSource cardSource)
+                        {
+                            return cardSource != null &&
+                                cardSource.Owner == card.Owner &&
+                                cardSource.HasText("Vemmon");
+                        }
+
+                        bool RootCondition(SelectCardEffect.Root root)
+                        {
+                            return true;
+                        }
+
+                        bool isUpDown()
+                        {
+                            return true;
+                        }
+
+                    }
+                }
+            }
+
+            #endregion
+
+            return cardEffects;
+        }
+    }
+}

+ 11 - 0
Assets/CardEffect/BT21/Black/BT21_056.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: dc9c0388487296444be271994bfa3d6e
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 392 - 0
Assets/CardEffect/BT21/Black/BT21_057.cs

@@ -0,0 +1,392 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace DCGO.CardEffects.BT21
+{
+    //Greymon
+    public class BT21_057 : CEntity_Effect
+    {
+        public override List<ICardEffect> CardEffects(EffectTiming timing, CardSource card)
+        {
+            List<ICardEffect> cardEffects = new List<ICardEffect>();
+
+            #region Alternative Digivolve Condition
+            if (timing == EffectTiming.None)
+            {
+                static bool PermanentCondition(Permanent targetPermanent)
+                {
+                    return targetPermanent.TopCard.HasLevel && targetPermanent.TopCard.Level == 3 && (targetPermanent.TopCard.ContainsCardName("Agumon") || targetPermanent.TopCard.EqualsTraits("ADVENTURE"));
+                }
+
+                cardEffects.Add(CardEffectFactory.AddSelfDigivolutionRequirementStaticEffect(permanentCondition: PermanentCondition, digivolutionCost: 2, ignoreDigivolutionRequirement: false, card: card, condition: null));
+            }
+            #endregion
+
+            #region On Play
+            if (timing == EffectTiming.OnEnterFieldAnyone)
+            {
+                ActivateClass activateClass = new ActivateClass();
+                activateClass.SetUpICardEffect("Forces 1 opponent Digimon attack Start of Main Phase", CanUseCondition, card);
+                activateClass.SetUpActivateClass(CanActivateCondition, ActivateCoroutine, -1, false, EffectDiscription());
+                cardEffects.Add(activateClass);
+
+                string EffectDiscription()
+                {
+                    return "[On Play] If you have [Tai Kamiya] or a Tamer with the [ADVENTURE] trait, give 1 of your opponent's Digimon \"[Start of Your Main Phase] This Digimon attacks.\" until their turn ends.";
+                }
+
+                bool PermanentCondition(Permanent permanent)
+                {
+                    if (CardEffectCommons.IsPermanentExistsOnOwnerBattleArea(permanent, card))
+                    {
+                        if (permanent.TopCard.EqualsCardName("Tai Kamiya"))
+                        {
+                            return true;
+                        }
+                        if (permanent.IsTamer & permanent.TopCard.EqualsTraits("ADVENTURE"))
+                        {
+                            return true;
+                        }
+                    }
+
+                    return false;
+                }
+
+                bool CanSelectPermanentCondition(Permanent permanent)
+                {
+                    return CardEffectCommons.IsPermanentExistsOnOpponentBattleAreaDigimon(permanent, card);
+                }
+
+                bool CanUseCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.CanTriggerOnPlay(hashtable, card);
+                }
+
+                bool CanActivateCondition(Hashtable hashtable)
+                {
+                    if (CardEffectCommons.IsExistOnBattleArea(card))
+                    {
+                        if (CardEffectCommons.HasMatchConditionOwnersPermanent(card, PermanentCondition))
+                        {
+                            if (CardEffectCommons.HasMatchConditionPermanent(CanSelectPermanentCondition))
+                            {
+                                return true;
+                            }
+                        }
+                    }
+
+                    return false;
+                }
+
+                IEnumerator ActivateCoroutine(Hashtable _hashtable)
+                {
+                    Permanent selectedPermanent = null;
+
+                    if (CardEffectCommons.HasMatchConditionPermanent(CanSelectPermanentCondition))
+                    {
+                        int maxCount = Math.Min(1, CardEffectCommons.MatchConditionPermanentCount(CanSelectPermanentCondition));
+
+                        SelectPermanentEffect selectPermanentEffect = GManager.instance.GetComponent<SelectPermanentEffect>();
+
+                        selectPermanentEffect.SetUp(
+                            selectPlayer: card.Owner,
+                            canTargetCondition: CanSelectPermanentCondition,
+                            canTargetCondition_ByPreSelecetedList: null,
+                            canEndSelectCondition: null,
+                            maxCount: maxCount,
+                            canNoSelect: false,
+                            canEndNotMax: false,
+                            selectPermanentCoroutine: SelectPermanentCoroutine,
+                            afterSelectPermanentCoroutine: null,
+                            mode: SelectPermanentEffect.Mode.Custom,
+                            cardEffect: activateClass);
+
+                        selectPermanentEffect.SetUpCustomMessage(
+                        $"Select 1 Digimon that will get effects.",
+                        $"The opponent is selecting 1 Digimon that will get effects.");
+
+                        yield return ContinuousController.instance.StartCoroutine(selectPermanentEffect.Activate());
+
+                        IEnumerator SelectPermanentCoroutine(Permanent permanent)
+                        {
+                            selectedPermanent = permanent;
+
+                            yield return null;
+                        }
+
+                        if (selectedPermanent != null)
+                        {
+                            ActivateClass activateClass1 = new ActivateClass();
+                            activateClass1.SetUpICardEffect("Attack with this Digimon", CanUseCondition1, selectedPermanent.TopCard);
+                            activateClass1.SetUpActivateClass(CanActivateCondition1, ActivateCoroutine1, -1, false, EffectDiscription1());
+                            activateClass1.SetEffectSourcePermanent(selectedPermanent);
+                            selectedPermanent.UntilOwnerTurnEndEffects.Add(GetCardEffect);
+
+                            if (!selectedPermanent.TopCard.CanNotBeAffected(activateClass))
+                            {
+                                yield return ContinuousController.instance.StartCoroutine(GManager.instance.GetComponent<Effects>().CreateDebuffEffect(selectedPermanent));
+                            }
+
+                            string EffectDiscription1()
+                            {
+                                return "[Start of Your Main Phase] Attack with this Digimon.";
+                            }
+
+                            bool CanUseCondition1(Hashtable hashtable1)
+                            {
+                                if (CardEffectCommons.IsPermanentExistsOnBattleArea(selectedPermanent))
+                                {
+                                    if (selectedPermanent.TopCard.Owner.GetBattleAreaDigimons().Contains(selectedPermanent))
+                                    {
+                                        if (GManager.instance.turnStateMachine.gameContext.TurnPlayer == selectedPermanent.TopCard.Owner)
+                                        {
+                                            return true;
+                                        }
+                                    }
+                                }
+
+                                return false;
+                            }
+
+                            bool CanActivateCondition1(Hashtable hashtable1)
+                            {
+                                if (CardEffectCommons.IsPermanentExistsOnBattleArea(selectedPermanent))
+                                {
+                                    if (!selectedPermanent.TopCard.CanNotBeAffected(activateClass))
+                                    {
+                                        if (selectedPermanent.CanAttack(activateClass1))
+                                        {
+                                            return true;
+                                        }
+                                    }
+                                }
+
+                                return false;
+                            }
+
+                            IEnumerator ActivateCoroutine1(Hashtable _hashtable1)
+                            {
+                                if (CardEffectCommons.IsPermanentExistsOnBattleArea(selectedPermanent))
+                                {
+                                    if (selectedPermanent.CanAttack(activateClass1))
+                                    {
+                                        SelectAttackEffect selectAttackEffect = GManager.instance.GetComponent<SelectAttackEffect>();
+
+                                        selectAttackEffect.SetUp(
+                                            attacker: selectedPermanent,
+                                            canAttackPlayerCondition: () => true,
+                                            defenderCondition: (permanent) => true,
+                                            cardEffect: activateClass1);
+
+                                        selectAttackEffect.SetCanNotSelectNotAttack();
+
+                                        yield return ContinuousController.instance.StartCoroutine(selectAttackEffect.Activate());
+                                    }
+                                }
+                            }
+
+                            ICardEffect GetCardEffect(EffectTiming _timing)
+                            {
+                                if (_timing == EffectTiming.OnStartMainPhase)
+                                {
+                                    return activateClass1;
+                                }
+
+                                return null;
+                            }
+                        }
+                    }
+                }
+            }
+            #endregion
+
+            #region When Digivolving
+            if (timing == EffectTiming.OnEnterFieldAnyone)
+            {
+                ActivateClass activateClass = new ActivateClass();
+                activateClass.SetUpICardEffect("Forces 1 opponent Digimon attack Start of Main Phase", CanUseCondition, card);
+                activateClass.SetUpActivateClass(CanActivateCondition, ActivateCoroutine, -1, false, EffectDiscription());
+                cardEffects.Add(activateClass);
+
+                string EffectDiscription()
+                {
+                    return "[When Digivolving] If you have [Tai Kamiya] or a Tamer with the [ADVENTURE] trait, give 1 of your opponent's Digimon \"[Start of Your Main Phase] This Digimon attacks.\" until their turn ends.";
+                }
+
+                bool PermanentCondition(Permanent permanent)
+                {
+                    if (CardEffectCommons.IsPermanentExistsOnOwnerBattleArea(permanent, card))
+                    {
+                        if (permanent.TopCard.EqualsCardName("Tai Kamiya"))
+                        {
+                            return true;
+                        }
+                        if (permanent.IsTamer & permanent.TopCard.EqualsTraits("ADVENTURE"))
+                        {
+                            return true;
+                        }
+                    }
+
+                    return false;
+                }
+
+                bool CanSelectPermanentCondition(Permanent permanent)
+                {
+                    return CardEffectCommons.IsPermanentExistsOnOpponentBattleAreaDigimon(permanent, card);
+                }
+
+                bool CanUseCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.CanTriggerWhenDigivolving(hashtable, card);
+                }
+
+                bool CanActivateCondition(Hashtable hashtable)
+                {
+                    if (CardEffectCommons.IsExistOnBattleArea(card))
+                    {
+                        if (CardEffectCommons.HasMatchConditionOwnersPermanent(card, PermanentCondition))
+                        {
+                            if (CardEffectCommons.HasMatchConditionPermanent(CanSelectPermanentCondition))
+                            {
+                                return true;
+                            }
+                        }
+                    }
+
+                    return false;
+                }
+
+                IEnumerator ActivateCoroutine(Hashtable _hashtable)
+                {
+                    Permanent selectedPermanent = null;
+
+                    if (CardEffectCommons.HasMatchConditionPermanent(CanSelectPermanentCondition))
+                    {
+                        int maxCount = Math.Min(1, CardEffectCommons.MatchConditionPermanentCount(CanSelectPermanentCondition));
+
+                        SelectPermanentEffect selectPermanentEffect = GManager.instance.GetComponent<SelectPermanentEffect>();
+
+                        selectPermanentEffect.SetUp(
+                            selectPlayer: card.Owner,
+                            canTargetCondition: CanSelectPermanentCondition,
+                            canTargetCondition_ByPreSelecetedList: null,
+                            canEndSelectCondition: null,
+                            maxCount: maxCount,
+                            canNoSelect: false,
+                            canEndNotMax: false,
+                            selectPermanentCoroutine: SelectPermanentCoroutine,
+                            afterSelectPermanentCoroutine: null,
+                            mode: SelectPermanentEffect.Mode.Custom,
+                            cardEffect: activateClass);
+
+                        selectPermanentEffect.SetUpCustomMessage(
+                        $"Select 1 Digimon that will get effects.",
+                        $"The opponent is selecting 1 Digimon that will get effects.");
+
+                        yield return ContinuousController.instance.StartCoroutine(selectPermanentEffect.Activate());
+
+                        IEnumerator SelectPermanentCoroutine(Permanent permanent)
+                        {
+                            selectedPermanent = permanent;
+
+                            yield return null;
+                        }
+
+                        if (selectedPermanent != null)
+                        {
+                            ActivateClass activateClass1 = new ActivateClass();
+                            activateClass1.SetUpICardEffect("Attack with this Digimon", CanUseCondition1, selectedPermanent.TopCard);
+                            activateClass1.SetUpActivateClass(CanActivateCondition1, ActivateCoroutine1, -1, false, EffectDiscription1());
+                            activateClass1.SetEffectSourcePermanent(selectedPermanent);
+                            selectedPermanent.UntilOwnerTurnEndEffects.Add(GetCardEffect);
+
+                            if (!selectedPermanent.TopCard.CanNotBeAffected(activateClass))
+                            {
+                                yield return ContinuousController.instance.StartCoroutine(GManager.instance.GetComponent<Effects>().CreateDebuffEffect(selectedPermanent));
+                            }
+
+                            string EffectDiscription1()
+                            {
+                                return "[Start of Your Main Phase] Attack with this Digimon.";
+                            }
+
+                            bool CanUseCondition1(Hashtable hashtable1)
+                            {
+                                if (CardEffectCommons.IsPermanentExistsOnBattleArea(selectedPermanent))
+                                {
+                                    if (selectedPermanent.TopCard.Owner.GetBattleAreaDigimons().Contains(selectedPermanent))
+                                    {
+                                        if (GManager.instance.turnStateMachine.gameContext.TurnPlayer == selectedPermanent.TopCard.Owner)
+                                        {
+                                            return true;
+                                        }
+                                    }
+                                }
+
+                                return false;
+                            }
+
+                            bool CanActivateCondition1(Hashtable hashtable1)
+                            {
+                                if (CardEffectCommons.IsPermanentExistsOnBattleArea(selectedPermanent))
+                                {
+                                    if (!selectedPermanent.TopCard.CanNotBeAffected(activateClass))
+                                    {
+                                        if (selectedPermanent.CanAttack(activateClass1))
+                                        {
+                                            return true;
+                                        }
+                                    }
+                                }
+
+                                return false;
+                            }
+
+                            IEnumerator ActivateCoroutine1(Hashtable _hashtable1)
+                            {
+                                if (CardEffectCommons.IsPermanentExistsOnBattleArea(selectedPermanent))
+                                {
+                                    if (selectedPermanent.CanAttack(activateClass1))
+                                    {
+                                        SelectAttackEffect selectAttackEffect = GManager.instance.GetComponent<SelectAttackEffect>();
+
+                                        selectAttackEffect.SetUp(
+                                            attacker: selectedPermanent,
+                                            canAttackPlayerCondition: () => true,
+                                            defenderCondition: (permanent) => true,
+                                            cardEffect: activateClass1);
+
+                                        selectAttackEffect.SetCanNotSelectNotAttack();
+
+                                        yield return ContinuousController.instance.StartCoroutine(selectAttackEffect.Activate());
+                                    }
+                                }
+                            }
+
+                            ICardEffect GetCardEffect(EffectTiming _timing)
+                            {
+                                if (_timing == EffectTiming.OnStartMainPhase)
+                                {
+                                    return activateClass1;
+                                }
+
+                                return null;
+                            }
+                        }
+                    }
+                }
+            }
+            #endregion
+
+            #region Reboot Inherit
+            if (timing == EffectTiming.None)
+            {
+                cardEffects.Add(CardEffectFactory.RebootSelfStaticEffect(isInheritedEffect: true, card: card, condition: null));
+            }
+            #endregion
+
+            return cardEffects;
+        }
+    }
+}

+ 11 - 0
Assets/CardEffect/BT21/Black/BT21_057.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 40a1512e23e018045a956346bfcef9f9
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 352 - 0
Assets/CardEffect/BT21/Black/BT21_058.cs

@@ -0,0 +1,352 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace DCGO.CardEffects.BT21
+{
+    //Snatchmon
+    public class BT21_058 : CEntity_Effect
+    {
+        public override List<ICardEffect> CardEffects(EffectTiming timing, CardSource card)
+        {
+            List<ICardEffect> cardEffects = new List<ICardEffect>();
+
+            #region On Play
+            if (timing == EffectTiming.OnEnterFieldAnyone)
+            {
+                ActivateClass activateClass = new ActivateClass();
+                activateClass.SetUpICardEffect("Reveal 3, add 1 [Vemmon] in text, trash rest, place up to 2 [Vemmon] from trash as 1 Digimon bottom evo cards", CanUseCondition, card);
+                activateClass.SetUpActivateClass(CanActivateCondition, ActivateCoroutine, -1, false, EffectDiscription());
+                cardEffects.Add(activateClass);
+
+                string EffectDiscription()
+                {
+                    return "[On Play] Reveal the top 3 cards of your deck. Add 1 card with [Vemmon] in its text among them to the hand. Trash the rest. Then, you may place up to 2 [Vemmon] from your trash as 1 of your Digimon's bottom digivolution cards.";
+                }
+
+                bool HasVemmonInText(CardSource cardSource)
+                {
+                    return cardSource.HasText("Vemmon");
+                }
+
+                bool IsVemmon(CardSource cardSource)
+                {
+                    return cardSource.EqualsCardName("Vemmon");
+                }
+
+                bool HasDigimonOnOwnerBattleArea(Permanent permanent)
+                {
+                    return CardEffectCommons.IsPermanentExistsOnOwnerBattleAreaDigimon(permanent, card);
+                }
+
+                bool CanUseCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.CanTriggerOnPlay(hashtable, card);
+                }
+
+                bool CanActivateCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.IsExistOnBattleAreaDigimon(card);
+                }
+
+                IEnumerator ActivateCoroutine(Hashtable hashtable)
+                {
+                    List<CardSource> selectedCards = new List<CardSource>();
+
+                    yield return ContinuousController.instance.StartCoroutine(CardEffectCommons.SimplifiedRevealDeckTopCardsAndSelect(
+                        revealCount: 3,
+                        simplifiedSelectCardConditions:
+                        new SimplifiedSelectCardConditionClass[]
+                        {
+                        new SimplifiedSelectCardConditionClass(
+                            canTargetCondition:HasVemmonInText,
+                            message: "Select 1 card with [Vemmon] in text.",
+                            mode: SelectCardEffect.Mode.AddHand,
+                            maxCount: 1,
+                            selectCardCoroutine: null),
+                        },
+                        remainingCardsPlace: RemainingCardsPlace.Trash,
+                        activateClass: activateClass,
+                        canNoSelect: false
+                    ));
+
+                    List<CardSource> selectedCardsFromTrash = new List<CardSource>();
+
+                    IEnumerator SelectCardCoroutine(CardSource cardSource)
+                    {
+                        selectedCardsFromTrash.Add(cardSource);
+
+                        yield return null;
+                    }
+
+                    int maxCountFromTrash = 2;
+
+                    SelectCardEffect selectCardEffect = GManager.instance.GetComponent<SelectCardEffect>();
+
+                    selectCardEffect.SetUp(
+                        canTargetCondition: IsVemmon,
+                        canTargetCondition_ByPreSelecetedList: null,
+                        canEndSelectCondition: null,
+                        canNoSelect: () => true,
+                        selectCardCoroutine: SelectCardCoroutine,
+                        afterSelectCardCoroutine: null,
+                        message: "Select up to 2 cards to place on bottom of digivolution cards.",
+                        maxCount: maxCountFromTrash,
+                        canEndNotMax: true,
+                        isShowOpponent: true,
+                        mode: SelectCardEffect.Mode.Custom,
+                        root: SelectCardEffect.Root.Trash,
+                        customRootCardList: null,
+                        canLookReverseCard: true,
+                        selectPlayer: card.Owner,
+                        cardEffect: activateClass);
+
+                    selectCardEffect.SetUpCustomMessage("Select up to 2 cards to place on bottom of digivolution cards.", "The opponent is selecting up to 2 cards to place on bottom of digivolution cards.");
+                    selectCardEffect.SetUpCustomMessage_ShowCard("Digivolution Card");
+
+                    yield return ContinuousController.instance.StartCoroutine(selectCardEffect.Activate());
+
+                    if (selectedCardsFromTrash.Count >= 1)
+                    {
+                        if (CardEffectCommons.HasMatchConditionPermanent(HasDigimonOnOwnerBattleArea))
+                        {
+                            int maxCountReceiverDigimon = 1;
+
+                            SelectPermanentEffect selectPermanentEffect = GManager.instance.GetComponent<SelectPermanentEffect>();
+
+                            selectPermanentEffect.SetUp(
+                                    selectPlayer: card.Owner,
+                                    canTargetCondition: HasDigimonOnOwnerBattleArea,
+                                    canTargetCondition_ByPreSelecetedList: null,
+                                    canEndSelectCondition: null,
+                                    maxCount: maxCountReceiverDigimon,
+                                    canNoSelect: true,
+                                    canEndNotMax: false,
+                                    selectPermanentCoroutine: SelectPermanentCoroutine,
+                                    afterSelectPermanentCoroutine: null,
+                                    mode: SelectPermanentEffect.Mode.Custom,
+                                    cardEffect: activateClass);
+
+                            selectPermanentEffect.SetUpCustomMessage("Select 1 Digimon that will get the digivolution card(s).", "The opponent is selecting 1 Digimon that will get the digivolution card(s).");
+
+                            yield return ContinuousController.instance.StartCoroutine(selectPermanentEffect.Activate());
+
+                            IEnumerator SelectPermanentCoroutine(Permanent permanent)
+                            {
+                                Permanent selectedPermanent = permanent;
+
+                                if (selectedPermanent != null)
+                                {
+                                    yield return ContinuousController.instance.StartCoroutine(selectedPermanent.AddDigivolutionCardsBottom(selectedCardsFromTrash, activateClass));
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            #endregion
+
+            #region When Digivolving
+            if (timing == EffectTiming.OnEnterFieldAnyone)
+            {
+                ActivateClass activateClass = new ActivateClass();
+                activateClass.SetUpICardEffect("Reveal 3, add 1 [Vemmon] in text, trash rest, place up to 2 [Vemmon] from trash as 1 Digimon bottom evo cards", CanUseCondition, card);
+                activateClass.SetUpActivateClass(CanActivateCondition, ActivateCoroutine, -1, false, EffectDiscription());
+                cardEffects.Add(activateClass);
+
+                string EffectDiscription()
+                {
+                    return "[When Digivolving] Reveal the top 3 cards of your deck. Add 1 card with [Vemmon] in its text among them to the hand. Trash the rest. Then, you may place up to 2 [Vemmon] from your trash as 1 of your Digimon's bottom digivolution cards.";
+                }
+
+                bool HasVemmonInText(CardSource cardSource)
+                {
+                    return cardSource.HasText("Vemmon");
+                }
+
+                bool IsVemmon(CardSource cardSource)
+                {
+                    return cardSource.EqualsCardName("Vemmon");
+                }
+
+                bool HasDigimonOnOwnerBattleArea(Permanent permanent)
+                {
+                    return CardEffectCommons.IsPermanentExistsOnOwnerBattleAreaDigimon(permanent, card);
+                }
+
+                bool CanUseCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.CanTriggerWhenDigivolving(hashtable, card);
+                }
+
+                bool CanActivateCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.IsExistOnBattleAreaDigimon(card);
+                }
+
+                IEnumerator ActivateCoroutine(Hashtable hashtable)
+                {
+                    List<CardSource> selectedCards = new List<CardSource>();
+
+                    yield return ContinuousController.instance.StartCoroutine(CardEffectCommons.SimplifiedRevealDeckTopCardsAndSelect(
+                        revealCount: 3,
+                        simplifiedSelectCardConditions:
+                        new SimplifiedSelectCardConditionClass[]
+                        {
+                        new SimplifiedSelectCardConditionClass(
+                            canTargetCondition:HasVemmonInText,
+                            message: "Select 1 card with [Vemmon] in text.",
+                            mode: SelectCardEffect.Mode.AddHand,
+                            maxCount: 1,
+                            selectCardCoroutine: null),
+                        },
+                        remainingCardsPlace: RemainingCardsPlace.Trash,
+                        activateClass: activateClass,
+                        canNoSelect: false
+                    ));
+
+                    List<CardSource> selectedCardsFromTrash = new List<CardSource>();
+
+                    IEnumerator SelectCardCoroutine(CardSource cardSource)
+                    {
+                        selectedCardsFromTrash.Add(cardSource);
+
+                        yield return null;
+                    }
+
+                    int maxCountFromTrash = 2;
+
+                    SelectCardEffect selectCardEffect = GManager.instance.GetComponent<SelectCardEffect>();
+
+                    selectCardEffect.SetUp(
+                        canTargetCondition: IsVemmon,
+                        canTargetCondition_ByPreSelecetedList: null,
+                        canEndSelectCondition: null,
+                        canNoSelect: () => true,
+                        selectCardCoroutine: SelectCardCoroutine,
+                        afterSelectCardCoroutine: null,
+                        message: "Select up to 2 cards to place on bottom of digivolution cards.",
+                        maxCount: maxCountFromTrash,
+                        canEndNotMax: true,
+                        isShowOpponent: true,
+                        mode: SelectCardEffect.Mode.Custom,
+                        root: SelectCardEffect.Root.Trash,
+                        customRootCardList: null,
+                        canLookReverseCard: true,
+                        selectPlayer: card.Owner,
+                        cardEffect: activateClass);
+
+                    selectCardEffect.SetUpCustomMessage("Select up to 2 cards to place on bottom of digivolution cards.", "The opponent is selecting up to 2 cards to place on bottom of digivolution cards.");
+                    selectCardEffect.SetUpCustomMessage_ShowCard("Digivolution Card");
+
+                    yield return ContinuousController.instance.StartCoroutine(selectCardEffect.Activate());
+
+                    if (selectedCardsFromTrash.Count >= 1)
+                    {
+                        if (CardEffectCommons.HasMatchConditionPermanent(HasDigimonOnOwnerBattleArea))
+                        {
+                            int maxCountReceiverDigimon = 1;
+
+                            SelectPermanentEffect selectPermanentEffect = GManager.instance.GetComponent<SelectPermanentEffect>();
+
+                            selectPermanentEffect.SetUp(
+                                    selectPlayer: card.Owner,
+                                    canTargetCondition: HasDigimonOnOwnerBattleArea,
+                                    canTargetCondition_ByPreSelecetedList: null,
+                                    canEndSelectCondition: null,
+                                    maxCount: maxCountReceiverDigimon,
+                                    canNoSelect: true,
+                                    canEndNotMax: false,
+                                    selectPermanentCoroutine: SelectPermanentCoroutine,
+                                    afterSelectPermanentCoroutine: null,
+                                    mode: SelectPermanentEffect.Mode.Custom,
+                                    cardEffect: activateClass);
+
+                            selectPermanentEffect.SetUpCustomMessage("Select 1 Digimon that will get the digivolution card(s).", "The opponent is selecting 1 Digimon that will get the digivolution card(s).");
+
+                            yield return ContinuousController.instance.StartCoroutine(selectPermanentEffect.Activate());
+
+                            IEnumerator SelectPermanentCoroutine(Permanent permanent)
+                            {
+                                Permanent selectedPermanent = permanent;
+
+                                if (selectedPermanent != null)
+                                {
+                                    yield return ContinuousController.instance.StartCoroutine(selectedPermanent.AddDigivolutionCardsBottom(selectedCardsFromTrash, activateClass));
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            #endregion
+
+            #region All Turns Inherited
+            if (timing == EffectTiming.OnDigivolutionCardReturnToDeckBottom)
+            {
+                ActivateClass activateClass = new ActivateClass();
+                activateClass.SetUpICardEffect("Delete 1 opponent Digimon with play cost 4 or less", CanUseCondition, card);
+                activateClass.SetUpActivateClass(CanActivateCondition, ActivateCoroutine, 1, false, EffectDiscription());
+                activateClass.SetIsInheritedEffect(true);
+                activateClass.SetHashString("Delete_BT21_058");
+                cardEffects.Add(activateClass);
+
+                string EffectDiscription()
+                {
+                    return "[All Turns] [Once Per Turn] When any [Vemmon] are returned to the bottom of the deck from this Digimon's digivolution cards, delete 1 of your opponent's Digimon with a play cost of 4 or less.";
+                }
+
+                bool CanSelectPermanentCondition(Permanent permanent)
+                {
+                    if (CardEffectCommons.IsPermanentExistsOnOpponentBattleAreaDigimon(permanent, card))
+                    {
+                        if (permanent.TopCard.HasPlayCost & permanent.TopCard.GetCostItself <= 4)
+                        {
+                            return true;
+                        }
+                    }
+
+                    return false;
+                }
+
+                bool CanUseCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.CanTriggerOnReturnToLibraryBottomDigivolutionCard(hashtable, cardSource => cardSource.EqualsCardName("Vemmon"), card);
+                }
+
+                bool CanActivateCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.IsExistOnBattleArea(card);
+                }
+
+                IEnumerator ActivateCoroutine(Hashtable _hashtable)
+                {
+                    if (CardEffectCommons.HasMatchConditionPermanent(CanSelectPermanentCondition))
+                    {
+                        int maxCount = Math.Min(1, CardEffectCommons.MatchConditionPermanentCount(CanSelectPermanentCondition));
+
+                        SelectPermanentEffect selectPermanentEffect = GManager.instance.GetComponent<SelectPermanentEffect>();
+
+                        selectPermanentEffect.SetUp(
+                            selectPlayer: card.Owner,
+                            canTargetCondition: CanSelectPermanentCondition,
+                            canTargetCondition_ByPreSelecetedList: null,
+                            canEndSelectCondition: null,
+                            maxCount: maxCount,
+                            canNoSelect: false,
+                            canEndNotMax: false,
+                            selectPermanentCoroutine: null,
+                            afterSelectPermanentCoroutine: null,
+                            mode: SelectPermanentEffect.Mode.Destroy,
+                            cardEffect: activateClass);
+
+                        yield return ContinuousController.instance.StartCoroutine(selectPermanentEffect.Activate());
+                    }
+                }
+            }
+            #endregion
+
+            return cardEffects;
+        }
+    }
+}

+ 11 - 0
Assets/CardEffect/BT21/Black/BT21_058.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 3f0863a26fd0aa644adc961f1b59c4fc
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 243 - 0
Assets/CardEffect/BT21/Black/BT21_059.cs

@@ -0,0 +1,243 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace DCGO.CardEffects.BT21
+{
+    //Timemon
+    public class BT21_059 : CEntity_Effect
+    {
+        public override List<ICardEffect> CardEffects(EffectTiming timing, CardSource card)
+        {
+            List<ICardEffect> cardEffects = new List<ICardEffect>();
+
+            #region Link Condition
+
+            if (timing == EffectTiming.None)
+            {
+                static bool PermanentCondition(Permanent targetPermanent)
+                {
+                    return targetPermanent.TopCard.HasAppmonTraits;
+                }
+
+                cardEffects.Add(CardEffectFactory.AddSelfLinkConditionStaticEffect(permanentCondition: PermanentCondition, linkCost: 0, card: card));
+            }
+
+            #endregion
+
+            #region App Fusion
+
+            if (timing == EffectTiming.None)
+            {
+                AddAppFusionConditionClass addAppFusionConditionClass = new AddAppFusionConditionClass();
+                addAppFusionConditionClass.SetUpICardEffect($"App Fusion", CanUseCondition, card);
+                addAppFusionConditionClass.SetUpAddAppFusionConditionClass(getAppFusionCondition: GetAppFusion);
+                addAppFusionConditionClass.SetNotShowUI(true);
+                cardEffects.Add(addAppFusionConditionClass);
+
+                bool CanUseCondition(Hashtable hashtable)
+                {
+                    return true;
+                }
+
+                AppFusionCondition GetAppFusion(CardSource cardSource)
+                {
+                    if (cardSource == card)
+                    {
+                        bool linkCondition(CardSource source)
+                        {
+                            return source != null;
+                        }
+
+                        bool digimonCondition(Permanent permanent)
+                        {
+                            return permanent != null &&
+                                permanent.TopCard != null &&
+                                permanent.TopCard.Owner == card.Owner &&
+                                permanent.TopCard.Owner.GetFieldPermanents().Contains(permanent) &&
+                                !card.CanNotEvolve(permanent) &&
+                                (permanent.TopCard.EqualsCardName("Watchmon") ||
+                                permanent.TopCard.EqualsCardName("Savemon") ||
+                                permanent.TopCard.EqualsCardName("Calendamon"));
+                        }
+
+                        AppFusionCondition AppFusionCondition = new AppFusionCondition(
+                            linkedCondition: linkCondition,
+                            selectLinkMessage: "1 Linked card",
+                            digimonCondition: digimonCondition,
+                            selectDigimonMessage: "1 of [Watchmon], [Savemon] and [Calendamon]",
+                            cost: 0);
+
+                        return AppFusionCondition;
+                    }
+
+                    return null;
+                }
+            }
+
+            #endregion
+
+            #region Blocker
+
+            if (timing == EffectTiming.None)
+            {
+                cardEffects.Add(CardEffectFactory.BlockerSelfStaticEffect(
+                    isInheritedEffect: false,
+                    card: card,
+                    condition: null));
+            }
+
+            #endregion
+
+            #region Your Turn
+
+            if (timing == EffectTiming.WhenLinked)
+            {
+                ActivateClass activateClass = new ActivateClass();
+                activateClass.SetUpICardEffect("<De-Digivolve 1>", CanUseCondition, card);
+                activateClass.SetUpActivateClass(CanActivateCondition, ActivateCoroutine, 1, false, EffectDiscription());
+                cardEffects.Add(activateClass);
+
+                string EffectDiscription()
+                {
+                    return "[Your Turn] [Once Per Turn] When this Digimon gets linked, <De-Digivolve 1> 1 of your opponent's Digimon.";
+                }
+
+                bool PermanentCondition(Permanent permanent)
+                {
+                    return permanent == card.PermanentOfThisCard();
+                }
+
+                bool CardCondition(CardSource source)
+                {
+                    return CardEffectCommons.IsExistOnBattleAreaDigimon(card);
+                }
+
+                bool IsOpponentsDigimon(Permanent permanent)
+                {
+                    return CardEffectCommons.IsPermanentExistsOnOpponentBattleAreaDigimon(permanent, card);
+                }
+
+                bool CanUseCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.IsExistOnBattleAreaDigimon(card) &&
+                        CardEffectCommons.CanTriggerWhenLinked(hashtable, PermanentCondition, CardCondition) &&
+                        CardEffectCommons.HasMatchConditionOpponentsPermanent(card, IsOpponentsDigimon);
+                }
+
+                bool CanActivateCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.IsExistOnBattleAreaDigimon(card);
+                }
+
+                IEnumerator ActivateCoroutine(Hashtable hashtable)
+                {
+                    if (CardEffectCommons.HasMatchConditionPermanent(IsOpponentsDigimon))
+                    {
+                        int maxCount = Math.Min(1, CardEffectCommons.MatchConditionPermanentCount(IsOpponentsDigimon));
+
+                        SelectPermanentEffect selectPermanentEffect = GManager.instance.GetComponent<SelectPermanentEffect>();
+
+                        selectPermanentEffect.SetUp(
+                            selectPlayer: card.Owner,
+                            canTargetCondition: IsOpponentsDigimon,
+                            canTargetCondition_ByPreSelecetedList: null,
+                            canEndSelectCondition: null,
+                            maxCount: maxCount,
+                            canNoSelect: false,
+                            canEndNotMax: false,
+                            selectPermanentCoroutine: SelectDeDigivolvePermanent,
+                            afterSelectPermanentCoroutine: null,
+                            mode: SelectPermanentEffect.Mode.Custom,
+                            cardEffect: activateClass);
+
+                        yield return ContinuousController.instance.StartCoroutine(selectPermanentEffect.Activate());
+                    }
+
+                    IEnumerator SelectDeDigivolvePermanent(Permanent permanent)
+                    {
+                        if (permanent != null)
+                            yield return ContinuousController.instance.StartCoroutine(new IDegeneration(permanent, 1, activateClass).Degeneration());
+                    }
+                }
+            }
+
+            #endregion
+
+            #region Link
+            if (timing == EffectTiming.OnDeclaration)
+            {
+                cardEffects.Add(CardEffectFactory.LinkEffect(card));
+            }
+            #endregion
+
+            #region When Linking
+
+            if (timing == EffectTiming.WhenLinked)
+            {
+                ActivateClass activateClass = new ActivateClass();
+                activateClass.SetUpICardEffect("<De-Digivolve 1>", CanUseCondition, card);
+                activateClass.SetUpActivateClass(CanActivateCondition, ActivateCoroutine, -1, false, EffectDiscription());
+                activateClass.SetIsLinkedEffect(true);
+                cardEffects.Add(activateClass);
+
+                string EffectDiscription()
+                {
+                    return "[When Linking] <De-Digivolve 1> 1 of your opponent's Digimon.";
+                }
+
+                bool IsOpponentsDigimon(Permanent permanent)
+                {
+                    return CardEffectCommons.IsPermanentExistsOnOpponentBattleAreaDigimon(permanent, card);
+                }
+
+                bool CanUseCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.IsExistOnBattleAreaDigimon(card) &&
+                        CardEffectCommons.CanTriggerWhenLinking(hashtable, null, card) &&
+                        CardEffectCommons.HasMatchConditionOpponentsPermanent(card, IsOpponentsDigimon);
+                }
+
+                bool CanActivateCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.IsExistOnBattleAreaDigimon(card);
+                }
+
+                IEnumerator ActivateCoroutine(Hashtable hashtable)
+                {
+                    if (CardEffectCommons.HasMatchConditionPermanent(IsOpponentsDigimon))
+                    {
+                        int maxCount = Math.Min(1, CardEffectCommons.MatchConditionPermanentCount(IsOpponentsDigimon));
+
+                        SelectPermanentEffect selectPermanentEffect = GManager.instance.GetComponent<SelectPermanentEffect>();
+
+                        selectPermanentEffect.SetUp(
+                            selectPlayer: card.Owner,
+                            canTargetCondition: IsOpponentsDigimon,
+                            canTargetCondition_ByPreSelecetedList: null,
+                            canEndSelectCondition: null,
+                            maxCount: maxCount,
+                            canNoSelect: false,
+                            canEndNotMax: false,
+                            selectPermanentCoroutine: SelectDeDigivolvePermanent,
+                            afterSelectPermanentCoroutine: null,
+                            mode: SelectPermanentEffect.Mode.Custom,
+                            cardEffect: activateClass);
+
+                        yield return ContinuousController.instance.StartCoroutine(selectPermanentEffect.Activate());
+                    }
+
+                    IEnumerator SelectDeDigivolvePermanent(Permanent permanent)
+                    {
+                        if (permanent != null)
+                            yield return ContinuousController.instance.StartCoroutine(new IDegeneration(permanent, 1, activateClass).Degeneration());
+                    }
+                }
+            }
+
+            #endregion
+
+            return cardEffects;
+        }
+    }
+}

+ 11 - 0
Assets/CardEffect/BT21/Black/BT21_059.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: fb07f2fa354946d41886fc2d5b3b0697
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 308 - 0
Assets/CardEffect/BT21/Black/BT21_060.cs

@@ -0,0 +1,308 @@
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace DCGO.CardEffects.BT21
+{
+    //Destromon
+    public class BT21_060 : CEntity_Effect
+    {
+        public override List<ICardEffect> CardEffects(EffectTiming timing, CardSource card)
+        {
+            List<ICardEffect> cardEffects = new List<ICardEffect>();
+
+            #region Alternative Digivolution Condition
+
+            if (timing == EffectTiming.None)
+            {
+                bool PermanentCondition(Permanent targetPermanent)
+                {
+                    if ((targetPermanent.TopCard.EqualsCardName("Vemmon")))
+                    {
+                        return true;
+                    }
+                    return false;
+                }
+
+                cardEffects.Add(CardEffectFactory.AddSelfDigivolutionRequirementStaticEffect(permanentCondition: PermanentCondition, digivolutionCost: 6, ignoreDigivolutionRequirement: false, card: card, condition: null));
+            }
+
+            #endregion
+
+            #region When Digivolving
+
+            if (timing == EffectTiming.OnEnterFieldAnyone)
+            {
+                ActivateClass activateClass = new ActivateClass();
+                activateClass.SetUpICardEffect("Can't trash stacked cards, then de-digivolve", CanUseCondition, card);
+                activateClass.SetUpActivateClass(CanActivateCondition, ActivateCoroutine, -1, false, EffectDiscription());
+                cardEffects.Add(activateClass);
+
+                string EffectDiscription()
+                {
+                    return "[When Digivolving] Until your opponent's turn ends, their effects can't trash this Digimon's top stacked cards. Then, to 1 of your opponent's Digimon, <De-Digivolve 1> for every 2 [Vemmon] in this Digimon's digivolution cards.";
+                }
+
+                bool CanUseCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.CanTriggerWhenDigivolving(hashtable, card);
+                }
+
+                bool CanActivateCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.IsExistOnBattleAreaDigimon(card);
+                }
+
+                bool SelectableOpponentsDigimon(Permanent permanent)
+                {
+                    return CardEffectCommons.IsPermanentExistsOnOpponentBattleAreaDigimon(permanent, card);
+                }
+
+                int VemmonInSourceDividedBy2()
+                {
+                    int vemmonCounter = 0;
+
+                    foreach (CardSource cardSource in card.PermanentOfThisCard().DigivolutionCards)
+                    {
+                        if (cardSource.EqualsCardName("Vemmon"))
+                        {
+                            vemmonCounter++;
+                        }
+                    }
+
+                    return vemmonCounter / 2;
+                }
+
+                IEnumerator ActivateCoroutine(Hashtable hashtable)
+                {
+                    Permanent selectedPermanent = card.PermanentOfThisCard();
+
+                    if (selectedPermanent != null)
+                    {
+                        ImmuneFromDeDigivolveClass immuneFromDeDigivolveClass = new ImmuneFromDeDigivolveClass();
+                        immuneFromDeDigivolveClass.SetUpICardEffect("Isn't affected by <De-Digivolve>", CanUseCondition1, selectedPermanent.TopCard);
+                        immuneFromDeDigivolveClass.SetUpImmuneFromDeDigivolveClass(PermanentCondition: PermanentCondition);
+                        selectedPermanent.UntilOpponentTurnEndEffects.Add((_timing) => immuneFromDeDigivolveClass);
+
+                        bool CanUseCondition1(Hashtable hashtable1)
+                        {
+                            return selectedPermanent.TopCard != null;
+                        }
+
+                        bool PermanentCondition(Permanent permanent)
+                        {
+                            return permanent == selectedPermanent;
+                        }
+
+                        CanNotTrashFromDigivolutionCardsClass canNotTrashFromDigivolutionCardsClass = new CanNotTrashFromDigivolutionCardsClass();
+                        canNotTrashFromDigivolutionCardsClass.SetUpICardEffect("[This Digimon's sources can't be trashed", CanUseCondition2, card);
+                        canNotTrashFromDigivolutionCardsClass.SetUpCanNotTrashFromDigivolutionCardsClass(CardCondition: CardCondition, CardEffectCondition: CardEffectCondition);
+                        cardEffects.Add(canNotTrashFromDigivolutionCardsClass);
+
+                        bool CanUseCondition2(Hashtable hashtable)
+                        {
+                            return CardEffectCommons.IsExistOnBattleArea(card);
+                        }
+
+                        bool CardCondition(CardSource cardSource)
+                        {
+                            return CardEffectCommons.IsExistOnBattleArea(card);
+                        }
+
+                        bool CardEffectCondition(ICardEffect cardEffect)
+                        {
+                            return CardEffectCommons.IsOpponentEffect(cardEffect, card);
+                        }
+                    }
+
+                    SelectPermanentEffect selectPermanentEffect = GManager.instance.GetComponent<SelectPermanentEffect>();
+
+                    selectPermanentEffect.SetUp(
+                        selectPlayer: card.Owner,
+                        canTargetCondition: SelectableOpponentsDigimon,
+                        canTargetCondition_ByPreSelecetedList: null,
+                        canEndSelectCondition: null,
+                        maxCount: 1,
+                        canNoSelect: false,
+                        canEndNotMax: false,
+                        selectPermanentCoroutine: SelectPermanentCoroutine,
+                        afterSelectPermanentCoroutine: null,
+                        mode: SelectPermanentEffect.Mode.Custom,
+                        cardEffect: activateClass);
+
+                    selectPermanentEffect.SetUpCustomMessage("Select 1 Digimon to De-Digivolve.", "The opponent is selecting 1 Digimon to De-Digivolve.");
+                    yield return ContinuousController.instance.StartCoroutine(selectPermanentEffect.Activate());
+
+                    IEnumerator SelectPermanentCoroutine(Permanent permanent)
+                    {
+                        yield return ContinuousController.instance.StartCoroutine(new IDegeneration(permanent, VemmonInSourceDividedBy2(), activateClass).Degeneration());
+                    }
+                }
+            }
+
+            #endregion
+
+            #region All Turns
+
+            if (timing == EffectTiming.WhenRemoveField)
+            {
+                ActivateClass activateClass = new ActivateClass();
+                activateClass.SetUpICardEffect("Play 1 [Vemmon] from source without paying the cost when leaving battle area.", CanUseCondition, card);
+                activateClass.SetUpActivateClass(CanActivateCondition, ActivateCoroutine, -1, true, EffectDiscription());
+                cardEffects.Add(activateClass);
+
+                string EffectDiscription()
+                {
+                    return "[All Turns] When this Digimon would leave the battle area, you may play 1 [Vemmon] from its digivolution cards without paying the cost.";
+                }
+
+                bool CanSelectSourceCardCondition(CardSource cardSource)
+                {
+                    return cardSource.EqualsCardName("Vemmon") &&
+                        CardEffectCommons.CanPlayAsNewPermanent(cardSource: cardSource, payCost: false, cardEffect: activateClass);
+                }
+
+                bool CanUseCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.IsExistOnBattleAreaDigimon(card) &&
+                        CardEffectCommons.CanTriggerWhenRemoveField(hashtable, card);
+                }
+
+                bool CanActivateCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.IsExistOnBattleAreaDigimon(card) &&
+                        card.PermanentOfThisCard().DigivolutionCards.Some(CanSelectSourceCardCondition);
+                }
+
+                IEnumerator ActivateCoroutine(Hashtable hashtable)
+                {
+                    List<CardSource> selectedCards = new List<CardSource>();
+
+                    SelectCardEffect selectCardEffect = GManager.instance.GetComponent<SelectCardEffect>();
+
+                    selectCardEffect.SetUp(
+                        canTargetCondition: CanSelectSourceCardCondition,
+                        canTargetCondition_ByPreSelecetedList: null,
+                        canEndSelectCondition: null,
+                        canNoSelect: () => true,
+                        selectCardCoroutine: SelectCardCoroutine,
+                        afterSelectCardCoroutine: null,
+                        message: "Select 1 digivolution card to play.",
+                        maxCount: 1,
+                        canEndNotMax: false,
+                        isShowOpponent: true,
+                        mode: SelectCardEffect.Mode.Custom,
+                        root: SelectCardEffect.Root.Custom,
+                        customRootCardList: card.PermanentOfThisCard().DigivolutionCards,
+                        canLookReverseCard: true,
+                        selectPlayer: card.Owner,
+                        cardEffect: activateClass);
+
+                    selectCardEffect.SetUpCustomMessage(
+                        "Select 1 digivolution card to play.",
+                        "The opponent is selecting 1 digivolution card to play.");
+                    selectCardEffect.SetUpCustomMessage_ShowCard("Played Card");
+
+                    yield return StartCoroutine(selectCardEffect.Activate());
+
+                    IEnumerator SelectCardCoroutine(CardSource cardSource)
+                    {
+                        selectedCards.Add(cardSource);
+
+                        yield return null;
+                    }
+
+                    yield return ContinuousController.instance.StartCoroutine(
+                        CardEffectCommons.PlayPermanentCards(
+                            cardSources: selectedCards,
+                            activateClass: activateClass,
+                            payCost: false,
+                            isTapped: false,
+                            root: SelectCardEffect.Root.DigivolutionCards,
+                            activateETB: true));
+                }
+            }
+
+            #endregion
+
+            #region Opponent's Turn Inherited
+            if (timing == EffectTiming.OnAllyAttack)
+            {
+                ActivateClass activateClass = new ActivateClass();
+                activateClass.SetUpICardEffect("Return 2 [Vemmon] from source to bottom of deck to end the attack", CanUseCondition, card);
+                activateClass.SetUpActivateClass(CanActivateCondition, ActivateCoroutine, 1, true, EffectDiscription());
+                activateClass.SetIsInheritedEffect(true);
+                activateClass.SetHashString("end-attack-BT21-060");
+                cardEffects.Add(activateClass);
+
+                string EffectDiscription()
+                {
+                    return "[Opponent's Turn] [Once Per Turn] When one of your opponent's Digimon attacks, by returning 2 [Vemmon] from this Digimon's digivolution cards to the bottom of the deck, end that attack.";
+                }
+
+                bool PermanentCondition(Permanent permanent)
+                {
+                    return CardEffectCommons.IsOpponentPermanent(permanent, card);
+                }
+
+                bool CanSelectVemmon(CardSource cardSource)
+                {
+                    return cardSource.EqualsCardName("Vemmon");
+                }
+
+                bool CanUseCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.IsExistOnBattleAreaDigimon(card) &&
+                        CardEffectCommons.IsOpponentTurn(card) &&
+                        CardEffectCommons.CanTriggerOnPermanentAttack(hashtable, PermanentCondition);
+                }
+
+                bool CanActivateCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.IsExistOnBattleAreaDigimon(card) &&
+                        card.PermanentOfThisCard().DigivolutionCards.Count(CanSelectVemmon) >= 2;
+                }
+
+                IEnumerator ActivateCoroutine(Hashtable _hashtable)
+                {
+                    SelectCardEffect selectCardEffect = GManager.instance.GetComponent<SelectCardEffect>();
+
+                    selectCardEffect.SetUp(
+                        canTargetCondition: CanSelectVemmon,
+                        canTargetCondition_ByPreSelecetedList: null,
+                        canEndSelectCondition: null,
+                        canNoSelect: () => false,
+                        selectCardCoroutine: null,
+                        afterSelectCardCoroutine: AfterSelectCardCoroutine,
+                        message: "Select 2 [Vemmon] to place at the bottom of the deck.",
+                        maxCount: 2,
+                        canEndNotMax: false,
+                        isShowOpponent: false,
+                        mode: SelectCardEffect.Mode.Custom,
+                        root: SelectCardEffect.Root.Custom,
+                        customRootCardList: card.PermanentOfThisCard().DigivolutionCards,
+                        canLookReverseCard: true,
+                        selectPlayer: card.Owner,
+                        cardEffect: activateClass);
+
+                    selectCardEffect.SetNotShowCard();
+                    selectCardEffect.SetNotAddLog();
+
+                    yield return ContinuousController.instance.StartCoroutine(selectCardEffect.Activate());
+
+                    IEnumerator AfterSelectCardCoroutine(List<CardSource> cardSources)
+                    {
+                        yield return ContinuousController.instance.StartCoroutine(CardObjectController.AddLibraryBottomCards(cardSources));
+
+                        yield return ContinuousController.instance.StartCoroutine(GManager.instance.GetComponent<Effects>().ShowCardEffect2(cardSources, "Deck Bottom Cards", true, true));
+
+                        GManager.instance.attackProcess.IsEndAttack = true;
+                    }
+                }
+            }
+            #endregion
+
+            return cardEffects;
+        }
+    }
+}

+ 11 - 0
Assets/CardEffect/BT21/Black/BT21_060.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 68ba11c435b069741809e74c3cd68641
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 303 - 0
Assets/CardEffect/BT21/Black/BT21_061.cs

@@ -0,0 +1,303 @@
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace DCGO.CardEffects.BT21
+{
+    //MetalGreymon
+    public class BT21_061 : CEntity_Effect
+    {
+        public override List<ICardEffect> CardEffects(EffectTiming timing, CardSource card)
+        {
+            List<ICardEffect> cardEffects = new List<ICardEffect>();
+
+            #region Shared Conditions
+            bool SelectableOpponentsDigimon(Permanent permanent)
+            {
+                return CardEffectCommons.IsPermanentExistsOnOpponentBattleAreaDigimon(permanent, card);
+            }
+
+            int OwnerTamerColorCountDividedBy2()
+            {
+                List<CardSource> tamerCards = new List<CardSource>();
+
+                foreach (Permanent permanent in card.Owner.GetBattleAreaPermanents())
+                {
+                    if (permanent.IsTamer)
+                    {
+                        tamerCards.Add(permanent.TopCard);
+                    }
+                }
+
+                return Combinations.GetDifferenetColorCardCount(tamerCards) / 2;
+            }
+            #endregion
+
+            #region Alternative Digivolve Condition
+            if (timing == EffectTiming.None)
+            {
+                static bool PermanentCondition(Permanent targetPermanent)
+                {
+                    return targetPermanent.TopCard.HasLevel && targetPermanent.TopCard.Level == 4 && (targetPermanent.TopCard.ContainsCardName("Greymon") || targetPermanent.TopCard.EqualsTraits("ADVENTURE"));
+                }
+
+                cardEffects.Add(CardEffectFactory.AddSelfDigivolutionRequirementStaticEffect(permanentCondition: PermanentCondition, digivolutionCost: 3, ignoreDigivolutionRequirement: false, card: card, condition: null));
+            }
+            #endregion
+
+            #region On Play
+            if (timing == EffectTiming.OnEnterFieldAnyone)
+            {
+                ActivateClass activateClass = new ActivateClass();
+                activateClass.SetUpICardEffect("De-Digivolve 1 of your opponents digimon", CanUseCondition, card);
+                activateClass.SetUpActivateClass(CanActivateCondition, ActivateCoroutine, -1, false, EffectDiscription());
+                cardEffects.Add(activateClass);
+
+                string EffectDiscription()
+                {
+                    return "[On Play] To 1 of your opponent's Digimon, <De-Digivolve 1> for every 2 of your Tamers' colors.";
+                }
+
+                bool CanUseCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.CanTriggerOnPlay(hashtable, card);
+                }
+
+                bool CanActivateCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.IsExistOnBattleAreaDigimon(card) &&
+                           CardEffectCommons.HasMatchConditionPermanent(SelectableOpponentsDigimon);
+                }
+
+                IEnumerator ActivateCoroutine(Hashtable hashtable)
+                {
+                    SelectPermanentEffect selectPermanentEffect = GManager.instance.GetComponent<SelectPermanentEffect>();
+
+                    selectPermanentEffect.SetUp(
+                        selectPlayer: card.Owner,
+                        canTargetCondition: SelectableOpponentsDigimon,
+                        canTargetCondition_ByPreSelecetedList: null,
+                        canEndSelectCondition: null,
+                        maxCount: 1,
+                        canNoSelect: false,
+                        canEndNotMax: false,
+                        selectPermanentCoroutine: SelectPermanentCoroutine,
+                        afterSelectPermanentCoroutine: null,
+                        mode: SelectPermanentEffect.Mode.Custom,
+                        cardEffect: activateClass);
+
+                    selectPermanentEffect.SetUpCustomMessage("Select 1 Digimon to De-Digivolve.", "The opponent is selecting 1 Digimon to De-Digivolve.");
+                    yield return ContinuousController.instance.StartCoroutine(selectPermanentEffect.Activate());
+
+                    IEnumerator SelectPermanentCoroutine(Permanent permanent)
+                    {
+                        yield return ContinuousController.instance.StartCoroutine(new IDegeneration(permanent, OwnerTamerColorCountDividedBy2(), activateClass).Degeneration());
+                    }
+                }
+            }
+            #endregion
+
+            #region When Digivolving
+            if (timing == EffectTiming.OnEnterFieldAnyone)
+            {
+                ActivateClass activateClass = new ActivateClass();
+                activateClass.SetUpICardEffect("De-Digivolve 1 of your opponents digimon", CanUseCondition, card);
+                activateClass.SetUpActivateClass(CanActivateCondition, ActivateCoroutine, -1, false, EffectDiscription());
+                cardEffects.Add(activateClass);
+
+                string EffectDiscription()
+                {
+                    return "[When Digivolving] To 1 of your opponent's Digimon, <De-Digivolve 1> for every 2 of your Tamers' colors.";
+                }
+
+                bool CanUseCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.CanTriggerWhenDigivolving(hashtable, card);
+                }
+
+                bool CanActivateCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.IsExistOnBattleAreaDigimon(card) &&
+                           CardEffectCommons.HasMatchConditionPermanent(SelectableOpponentsDigimon);
+                }
+
+                IEnumerator ActivateCoroutine(Hashtable hashtable)
+                {
+                    SelectPermanentEffect selectPermanentEffect = GManager.instance.GetComponent<SelectPermanentEffect>();
+
+                    selectPermanentEffect.SetUp(
+                        selectPlayer: card.Owner,
+                        canTargetCondition: SelectableOpponentsDigimon,
+                        canTargetCondition_ByPreSelecetedList: null,
+                        canEndSelectCondition: null,
+                        maxCount: 1,
+                        canNoSelect: false,
+                        canEndNotMax: false,
+                        selectPermanentCoroutine: SelectPermanentCoroutine,
+                        afterSelectPermanentCoroutine: null,
+                        mode: SelectPermanentEffect.Mode.Custom,
+                        cardEffect: activateClass);
+
+                    selectPermanentEffect.SetUpCustomMessage("Select 1 Digimon to De-Digivolve.", "The opponent is selecting 1 Digimon to De-Digivolve.");
+                    yield return ContinuousController.instance.StartCoroutine(selectPermanentEffect.Activate());
+
+                    IEnumerator SelectPermanentCoroutine(Permanent permanent)
+                    {
+                        yield return ContinuousController.instance.StartCoroutine(new IDegeneration(permanent, OwnerTamerColorCountDividedBy2(), activateClass).Degeneration());
+                    }
+                }
+            }
+            #endregion
+
+            #region Your Turn
+            if (timing == EffectTiming.OnEnterFieldAnyone)
+            {
+                ActivateClass activateClass = new ActivateClass();
+                activateClass.SetUpICardEffect("Gain alliance then attack", CanUseCondition, card);
+                activateClass.SetUpActivateClass(CanActivateCondition, ActivateCoroutine, 1, false, EffectDiscription());
+                activateClass.SetHashString("alliance-attack-BT21-061");
+                cardEffects.Add(activateClass);
+
+                string EffectDiscription()
+                {
+                    return "[Your Turn][Once Per Turn] When your other Digimon are played or digivolve, if any of them have the [ADVENTURE] trait, 1 of your Digimon gains <Alliance> for the turn. Then, 1 of your Digimon may attack.";
+                }
+
+                bool MyDigimonPlayedDigid(Permanent permanent)
+                {
+                    if (CardEffectCommons.IsPermanentExistsOnOwnerBattleAreaDigimon(permanent, card) && permanent != card.PermanentOfThisCard())
+                    {
+                        return permanent.TopCard.EqualsTraits("ADVENTURE");
+                    }
+                    return false;
+                }
+
+                bool MyDigimonAlliance(Permanent permanent)
+                {
+                    return CardEffectCommons.IsPermanentExistsOnOwnerBattleAreaDigimon(permanent, card);
+                }
+
+                bool MyDigimonAttacking(Permanent permanent)
+                {
+                    return CardEffectCommons.IsPermanentExistsOnOwnerBattleAreaDigimon(permanent, card) &&
+                           permanent.CanAttack(activateClass);
+                }
+
+                bool CanUseCondition(Hashtable hashtable)
+                {
+                    if (CardEffectCommons.IsExistOnBattleAreaDigimon(card))
+                    {
+                        if (CardEffectCommons.IsOwnerTurn(card))
+                        {
+                            if (CardEffectCommons.CanTriggerOnPermanentPlay(hashtable, MyDigimonPlayedDigid))
+                                return true;
+
+                            if (CardEffectCommons.CanTriggerWhenPermanentDigivolving(hashtable, MyDigimonPlayedDigid))
+                                return true;
+                        }
+                    }
+
+                    return false;
+                }
+
+                bool CanActivateCondition(Hashtable hashtable)
+                {
+                    if (CardEffectCommons.IsExistOnBattleAreaDigimon(card))
+                    {
+                        return true;
+                    }
+
+                    return false;
+                }
+
+                IEnumerator ActivateCoroutine(Hashtable hashtable)
+                {
+                    if (CardEffectCommons.HasMatchConditionPermanent(MyDigimonAlliance))
+                    {
+                        SelectPermanentEffect selectPermanentEffect = GManager.instance.GetComponent<SelectPermanentEffect>();
+
+                        selectPermanentEffect.SetUp(
+                            selectPlayer: card.Owner,
+                            canTargetCondition: MyDigimonAlliance,
+                            canTargetCondition_ByPreSelecetedList: null,
+                            canEndSelectCondition: null,
+                            maxCount: 1,
+                            canNoSelect: false,
+                            canEndNotMax: false,
+                            selectPermanentCoroutine: SelectBoostedDigimon,
+                            afterSelectPermanentCoroutine: null,
+                            mode: SelectPermanentEffect.Mode.Custom,
+                            cardEffect: activateClass);
+
+                        selectPermanentEffect.SetUpCustomMessage("Select 1 Digimon to gain <Alliance>", "The opponent is selecting 1 Digimon to gain <Alliance>");
+
+                        yield return ContinuousController.instance.StartCoroutine(selectPermanentEffect.Activate());
+
+                        IEnumerator SelectBoostedDigimon(Permanent target)
+                        {
+                            yield return ContinuousController.instance.StartCoroutine(CardEffectCommons.GainAlliance(targetPermanent: target, effectDuration: EffectDuration.UntilEachTurnEnd, activateClass: activateClass)); ;
+                        }
+                    }
+
+                    if (CardEffectCommons.HasMatchConditionPermanent(MyDigimonAttacking))
+                    {
+                        Permanent selectedPermanent = null;
+                        SelectPermanentEffect selectPermanentEffect = GManager.instance.GetComponent<SelectPermanentEffect>();
+
+                        selectPermanentEffect.SetUp(
+                            selectPlayer: card.Owner,
+                            canTargetCondition: MyDigimonAttacking,
+                            canTargetCondition_ByPreSelecetedList: null,
+                            canEndSelectCondition: null,
+                            maxCount: 1,
+                            canNoSelect: false,
+                            canEndNotMax: false,
+                            selectPermanentCoroutine: SelectPermanentCoroutine,
+                            afterSelectPermanentCoroutine: null,
+                            mode: SelectPermanentEffect.Mode.Custom,
+                            cardEffect: activateClass);
+
+                        selectPermanentEffect.SetUpCustomMessage("Select 1 Digimon to attack.", "The opponent is selecting 1 Digimon to attack.");
+
+                        yield return ContinuousController.instance.StartCoroutine(selectPermanentEffect.Activate());
+
+                        IEnumerator SelectPermanentCoroutine(Permanent permanent)
+                        {
+                            selectedPermanent = permanent;
+
+                            yield return null;
+                        }
+
+                        if (selectedPermanent.CanAttack(activateClass))
+                        {
+                            SelectAttackEffect selectAttackEffect = GManager.instance.GetComponent<SelectAttackEffect>();
+
+                            selectAttackEffect.SetUp(
+                                attacker: selectedPermanent,
+                                canAttackPlayerCondition: () => true,
+                                defenderCondition: _ => true,
+                                cardEffect: activateClass);
+
+                            yield return ContinuousController.instance.StartCoroutine(selectAttackEffect.Activate());
+                        }
+                    }
+                }
+            }
+            #endregion
+
+            #region Alliance Inherit
+            if (timing == EffectTiming.OnAllyAttack)
+            {
+                bool Condition()
+                {
+                    return CardEffectCommons.IsExistOnBattleArea(card);
+                }
+
+                cardEffects.Add(CardEffectFactory.AllianceSelfEffect(isInheritedEffect: true, card: card, condition: Condition));
+            }
+            #endregion
+
+            return cardEffects;
+        }
+    }
+}

+ 11 - 0
Assets/CardEffect/BT21/Black/BT21_061.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 89a70d6edfcc9dc4cac54f4f5d33626b
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 372 - 0
Assets/CardEffect/BT21/Black/BT21_062.cs

@@ -0,0 +1,372 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace DCGO.CardEffects.BT21
+{
+    //Galacticmon
+    public class BT21_062 : CEntity_Effect
+    {
+        public override List<ICardEffect> CardEffects(EffectTiming timing, CardSource card)
+        {
+            List<ICardEffect> cardEffects = new List<ICardEffect>();
+
+            #region Alternative Digivolve Condition
+            if (timing == EffectTiming.None)
+            {
+                bool PermanentCondition(Permanent targetPermanent)
+                {
+                    return targetPermanent.TopCard.EqualsCardName("Snatchmon");
+                }
+
+                cardEffects.Add(CardEffectFactory.AddSelfDigivolutionRequirementStaticEffect(permanentCondition: PermanentCondition, digivolutionCost: 9, ignoreDigivolutionRequirement: false, card: card, condition: null));
+            }
+            #endregion
+
+            #region When Digivolving
+            if (timing == EffectTiming.OnEnterFieldAnyone)
+            {
+                ActivateClass activateClass = new ActivateClass();
+                activateClass.SetUpICardEffect("Place 4 cards from trash to digivolution cards to use [Ragnarok Cannon]", CanUseCondition, card);
+                activateClass.SetUpActivateClass(CanActivateCondition, ActivateCoroutine, -1, true, EffectDiscription());
+                cardEffects.Add(activateClass);
+
+                string EffectDiscription()
+                {
+                    return "[When Digivolving] By placing 4 cards with [Vemmon] in their texts from your trash as this Digimon's bottom digivolution cards, you may use 1 [Ragnarok Cannon] from your hand or trash without paying the cost.";
+                }
+
+                bool CanSelectCardCondition(CardSource cardSource)
+                {
+                    if (cardSource.HasText("Vemmon"))
+                    {
+                        return true;
+                    }
+
+                    return false;
+                }
+
+                bool CanUseCondition(Hashtable hashtable)
+                {
+                    if (CardEffectCommons.IsExistOnBattleAreaDigimon(card))
+                    {
+                        if (CardEffectCommons.CanTriggerWhenDigivolving(hashtable, card))
+                        {
+                            return true;
+                        }
+                    }
+
+                    return false;
+                }
+
+                bool CanActivateCondition(Hashtable hashtable)
+                {
+                    if (CardEffectCommons.IsExistOnBattleArea(card))
+                    {
+                        if (CardEffectCommons.HasMatchConditionOwnersCardInTrash(card, CanSelectCardCondition))
+                        {
+                            return true;
+                        }
+                    }
+
+                    return false;
+                }
+
+                bool CanSelectCardCondition1(CardSource cardSource)
+                {
+                    if (cardSource.EqualsCardName("Ragnarok Cannon"))
+                    {
+                        if (cardSource.HasUseCost)
+                        {
+                            if (!cardSource.CanNotPlayThisOption)
+                            {
+                                return true;
+                            }
+                        }
+                    }
+
+                    return false;
+                }
+
+                IEnumerator ActivateCoroutine(Hashtable _hashtable)
+                {
+                    if (CardEffectCommons.IsExistOnBattleArea(card))
+                    {
+                        bool added = false;
+
+                        if (CardEffectCommons.HasMatchConditionOwnersCardInTrash(card, CanSelectCardCondition))
+                        {
+                            List<CardSource> selectedCards = new List<CardSource>();
+
+                            int maxCount = 4;
+
+                            SelectCardEffect selectCardEffect = GManager.instance.GetComponent<SelectCardEffect>();
+
+                            selectCardEffect.SetUp(
+                                canTargetCondition: CanSelectCardCondition,
+                                canTargetCondition_ByPreSelecetedList: null,
+                                canEndSelectCondition: null,
+                                canNoSelect: () => true,
+                                selectCardCoroutine: SelectCardCoroutine,
+                                afterSelectCardCoroutine: null,
+                                message: "Select 4 cards to place on bottom of digivolution cards.",
+                                maxCount: maxCount,
+                                canEndNotMax: false,
+                                isShowOpponent: true,
+                                mode: SelectCardEffect.Mode.Custom,
+                                root: SelectCardEffect.Root.Trash,
+                                customRootCardList: null,
+                                canLookReverseCard: true,
+                                selectPlayer: card.Owner,
+                                cardEffect: activateClass);
+
+                            selectCardEffect.SetUpCustomMessage_ShowCard("Digivolution Card");
+                            selectCardEffect.SetUpCustomMessage("Select 4 cards to place on bottom of digivolution cards.", "The opponent is selecting 4 cards to place on bottom of digivolution cards.");
+
+                            yield return ContinuousController.instance.StartCoroutine(selectCardEffect.Activate());
+
+                            IEnumerator SelectCardCoroutine(CardSource cardSource)
+                            {
+                                selectedCards.Add(cardSource);
+
+                                yield return null;
+                            }
+
+                            if (selectedCards.Count >= 4)
+                            {
+                                yield return ContinuousController.instance.StartCoroutine(card.PermanentOfThisCard().AddDigivolutionCardsBottom(
+                                    selectedCards,
+                                    activateClass));
+
+                                added = true;
+                            }
+                        }
+
+                        if (added)
+                        {
+                            List<CardSource> selectedCards = new List<CardSource>();
+
+                            if (card.Owner.HandCards.Count(CanSelectCardCondition1) >= 1)
+                            {
+                                int maxCount = 1;
+
+                                SelectHandEffect selectHandEffect = GManager.instance.GetComponent<SelectHandEffect>();
+
+                                selectHandEffect.SetUp(
+                                    selectPlayer: card.Owner,
+                                    canTargetCondition: CanSelectCardCondition1,
+                                    canTargetCondition_ByPreSelecetedList: null,
+                                    canEndSelectCondition: null,
+                                    maxCount: maxCount,
+                                    canNoSelect: true,
+                                    canEndNotMax: false,
+                                    isShowOpponent: true,
+                                    selectCardCoroutine: SelectCardCoroutine,
+                                    afterSelectCardCoroutine: null,
+                                    mode: SelectHandEffect.Mode.Custom,
+                                    cardEffect: activateClass);
+
+                                selectHandEffect.SetUpCustomMessage(
+                                    "Select 1 option card to use.",
+                                    "The opponent is selecting 1 option card to use.");
+                                selectHandEffect.SetUpCustomMessage_ShowCard("Used Card");
+
+                                yield return StartCoroutine(selectHandEffect.Activate());
+
+                                IEnumerator SelectCardCoroutine(CardSource cardSource)
+                                {
+                                    selectedCards.Add(cardSource);
+
+                                    yield return null;
+                                }
+                            }
+
+                            if (selectedCards.Count >= 1)
+                            {
+                                yield return ContinuousController.instance.StartCoroutine(
+                                    CardEffectCommons.PlayOptionCards(
+                                        cardSources: selectedCards,
+                                        activateClass: activateClass,
+                                        payCost: false,
+                                        root: SelectCardEffect.Root.Hand
+                                    )
+                                );
+                            }
+                        }
+                    }
+                }
+            }
+            #endregion
+
+            #region Start of Your Main Phase
+            if (timing == EffectTiming.OnStartMainPhase)
+            {
+                ActivateClass activateClass = new ActivateClass();
+                activateClass.SetUpICardEffect("Delete 1 oppont Digimon", CanUseCondition, card);
+                activateClass.SetUpActivateClass(CanActivateCondition, ActivateCoroutine, -1, false, EffectDiscription());
+                cardEffects.Add(activateClass);
+
+                string EffectDiscription()
+                {
+                    return "[Start of Your Main Phase] Delete 1 of your opponent's Digimon.";
+                }
+
+                bool CanSelectPermanentCondition(Permanent permanent)
+                {
+                    return CardEffectCommons.IsPermanentExistsOnOpponentBattleAreaDigimon(permanent, card);
+                }
+
+                bool CanUseCondition(Hashtable hashtable)
+                {
+                    if (CardEffectCommons.IsExistOnBattleArea(card))
+                    {
+                        if (CardEffectCommons.IsOwnerTurn(card))
+                        {
+                            return true;
+                        }
+                    }
+
+                    return false;
+                }
+
+                bool CanActivateCondition(Hashtable hashtable)
+                {
+                    if (CardEffectCommons.IsExistOnBattleAreaDigimon(card))
+                    {
+                        if (card.Owner.Enemy.GetBattleAreaDigimons().Count >= 1)
+                        {
+                            return true;
+                        }
+                    }
+
+                    return false;
+                }
+
+                IEnumerator ActivateCoroutine(Hashtable _hashtable)
+                {
+                    if (CardEffectCommons.HasMatchConditionPermanent(CanSelectPermanentCondition))
+                    {
+                        int maxCount = Math.Min(1, CardEffectCommons.MatchConditionPermanentCount(CanSelectPermanentCondition));
+
+                        SelectPermanentEffect selectPermanentEffect = GManager.instance.GetComponent<SelectPermanentEffect>();
+
+                        selectPermanentEffect.SetUp(
+                            selectPlayer: card.Owner,
+                            canTargetCondition: CanSelectPermanentCondition,
+                            canTargetCondition_ByPreSelecetedList: null,
+                            canEndSelectCondition: null,
+                            maxCount: maxCount,
+                            canNoSelect: false,
+                            canEndNotMax: false,
+                            selectPermanentCoroutine: null,
+                            afterSelectPermanentCoroutine: null,
+                            mode: SelectPermanentEffect.Mode.Destroy,
+                            cardEffect: activateClass);
+
+                        yield return ContinuousController.instance.StartCoroutine(selectPermanentEffect.Activate());
+                    }
+                }
+            }
+            #endregion
+
+            #region All Turns
+            if (timing == EffectTiming.WhenRemoveField)
+            {
+                ActivateClass activateClass = new ActivateClass();
+                activateClass.SetUpICardEffect("Return 4 [Vemmon] from evo cards to bottom of deck to prevent this Digimon from leaving Battle Area", CanUseCondition, card);
+                activateClass.SetUpActivateClass(CanActivateCondition, ActivateCoroutine, -1, true, EffectDiscription());
+                cardEffects.Add(activateClass);
+
+                string EffectDiscription()
+                {
+                    return "[All Turns] When this Digimon would leave the battle area, by returning 4 [Vemmon] from its digivolution cards to the bottom of the deck, it doesn't leave.";
+                }
+
+                bool CanSelectVemmon(CardSource cardSource)
+                {
+                    return cardSource.EqualsCardName("Vemmon");
+                }
+
+                bool CanUseCondition(Hashtable hashtable)
+                {
+                    if (CardEffectCommons.IsExistOnBattleAreaDigimon(card))
+                    {
+                        if (CardEffectCommons.CanTriggerWhenRemoveField(hashtable, card))
+                        {
+                            return true;
+                        }
+                    }
+
+                    return false;
+                }
+
+                bool CanActivateCondition(Hashtable hashtable)
+                {
+                    if (CardEffectCommons.IsExistOnBattleAreaDigimon(card))
+                    {
+                        if (card.PermanentOfThisCard().DigivolutionCards.Count(CanSelectVemmon) >= 4)
+                        {
+                            return true;
+                        }
+                    }
+
+                    return false;
+                }
+
+                IEnumerator ActivateCoroutine(Hashtable hashtable)
+                {
+                    bool canSelectDigivolutionCards = CardEffectCommons.IsExistOnBattleAreaDigimon(card)
+                         && card.PermanentOfThisCard().DigivolutionCards.Count(CanSelectVemmon) >= 4;
+
+                    if (canSelectDigivolutionCards)
+                    {
+                        SelectCardEffect selectCardEffect = GManager.instance.GetComponent<SelectCardEffect>();
+
+                        selectCardEffect.SetUp(
+                        canTargetCondition: CanSelectVemmon,
+                        canTargetCondition_ByPreSelecetedList: null,
+                        canEndSelectCondition: null,
+                        canNoSelect: () => false,
+                        selectCardCoroutine: null,
+                        afterSelectCardCoroutine: AfterSelectCardCoroutine,
+                        message: "Select 4 [Vemmon] to place at the bottom of the deck.",
+                        maxCount: 1,
+                        canEndNotMax: false,
+                        isShowOpponent: false,
+                        mode: SelectCardEffect.Mode.Custom,
+                        root: SelectCardEffect.Root.Custom,
+                        customRootCardList: card.PermanentOfThisCard().DigivolutionCards,
+                        canLookReverseCard: true,
+                        selectPlayer: card.Owner,
+                        cardEffect: activateClass);
+
+                        selectCardEffect.SetNotShowCard();
+                        selectCardEffect.SetNotAddLog();
+
+                        yield return ContinuousController.instance.StartCoroutine(selectCardEffect.Activate());
+
+                        IEnumerator AfterSelectCardCoroutine(List<CardSource> cardSources)
+                        {
+                            yield return ContinuousController.instance.StartCoroutine(CardObjectController.AddLibraryBottomCards(cardSources));
+
+                            yield return ContinuousController.instance.StartCoroutine(GManager.instance.GetComponent<Effects>().ShowCardEffect2(cardSources, "Deck Bottom Cards", true, true));
+
+                            Permanent thisCardPermanent = card.PermanentOfThisCard();
+
+                            thisCardPermanent.willBeRemoveField = false;
+
+                            thisCardPermanent.HideDeleteEffect();
+                            thisCardPermanent.HideHandBounceEffect();
+                            thisCardPermanent.HideDeckBounceEffect();
+                            thisCardPermanent.HideWillRemoveFieldEffect();
+                        }
+                    }
+                }
+            }
+            #endregion
+
+            return cardEffects;
+        }
+    }
+}

+ 11 - 0
Assets/CardEffect/BT21/Black/BT21_062.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: efbb3183461d5e349bb92a97b4db9272
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 132 - 0
Assets/CardEffect/BT21/Black/BT21_087.cs

@@ -0,0 +1,132 @@
+using System.Collections;
+using System.Collections.Generic;
+
+namespace DCGO.CardEffects.BT21
+{
+    //Zenith
+    public class BT21_087 : CEntity_Effect
+    {
+        public override List<ICardEffect> CardEffects(EffectTiming timing, CardSource card)
+        {
+            List<ICardEffect> cardEffects = new List<ICardEffect>();
+
+            #region Start of Your Turn
+
+            if (timing == EffectTiming.OnStartTurn)
+            {
+                cardEffects.Add(CardEffectFactory.SetMemoryTo3TamerEffect(card));
+            }
+
+            #endregion
+
+            #region On Play
+
+            if (timing == EffectTiming.OnEnterFieldAnyone)
+            {
+                ActivateClass activateClass = new ActivateClass();
+                activateClass.SetUpICardEffect($"Reveal the top 3 cards of deck", CanUseCondition, card);
+                activateClass.SetUpActivateClass(CanActivateCondition, ActivateCoroutine, -1, false, EffectDiscription());
+                cardEffects.Add(activateClass);
+
+                string EffectDiscription()
+                {
+                    return "[On Play] Reveal the top 3 cards of your deck. Among them, play 1 [Vemmon] without paying the cost or add 1 card with [Vemmon] in its text to the hand. Trash the rest.";
+                }
+
+                bool CanSelectCardCondition(CardSource cardSource)
+                {
+                    return cardSource.HasText("Vemmon");
+                }
+
+                bool CanUseCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.CanTriggerOnPlay(hashtable, card);
+                }
+
+                bool CanActivateCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.IsExistOnBattleArea(card) &&
+                           card.Owner.LibraryCards.Count >= 1;
+                }
+
+                IEnumerator ActivateCoroutine(Hashtable _hashtable)
+                {
+                    if (card.Owner.LibraryCards.Count == 0) yield break;
+
+                    List<CardSource> selectedCards = new List<CardSource>();
+
+                    yield return ContinuousController.instance.StartCoroutine(CardEffectCommons.SimplifiedRevealDeckTopCardsAndSelect(
+                        revealCount: 3,
+                        simplifiedSelectCardConditions:
+                        new SimplifiedSelectCardConditionClass[]
+                        {
+                        new SimplifiedSelectCardConditionClass(
+                            canTargetCondition:CanSelectCardCondition,
+                            message: "Select 1 [Vemmon] or 1 card with [Vemmon] in its text.",
+                            mode: SelectCardEffect.Mode.Custom,
+                            maxCount: 1,
+                            selectCardCoroutine: SelectCardCoroutine),
+                        },
+                        remainingCardsPlace: RemainingCardsPlace.Trash,
+                        activateClass: activateClass,
+                        canNoSelect: true
+                    ));
+
+                    IEnumerator SelectCardCoroutine(CardSource cardSource)
+                    {
+                        selectedCards.Add(cardSource);
+                        yield return null;
+                    }
+
+                    bool playCard = false;
+
+                    if (selectedCards[0].EqualsCardName("Vemmon"))
+                    {
+                        List<SelectionElement<bool>> selectionElements = new List<SelectionElement<bool>>()
+                        {
+                            new SelectionElement<bool>(message: $"Play", value : true, spriteIndex: 0),
+                            new SelectionElement<bool>(message: $"Add to your hand", value : false, spriteIndex: 1),
+                        };
+
+                        string selectPlayerMessage = "Wll you play this card or add it to your hand?";
+                        string notSelectPlayerMessage = "The opponent is choosing whether to play the selected card or add it to their hand.";
+
+                        GManager.instance.userSelectionManager.SetBoolSelection(selectionElements: selectionElements, selectPlayer: card.Owner, selectPlayerMessage: selectPlayerMessage, notSelectPlayerMessage: notSelectPlayerMessage);
+
+                        yield return ContinuousController.instance.StartCoroutine(GManager.instance.userSelectionManager.WaitForEndSelect());
+
+                        playCard = GManager.instance.userSelectionManager.SelectedBoolValue;
+                    }
+
+                    if (playCard)
+                    {
+                        yield return ContinuousController.instance.StartCoroutine(CardEffectCommons.PlayPermanentCards(
+                            cardSources: selectedCards,
+                            activateClass: activateClass,
+                            payCost: false,
+                            isTapped: false,
+                            root: SelectCardEffect.Root.Library,
+                            activateETB: true));
+                    }
+                    else
+                    {
+                        yield return ContinuousController.instance.StartCoroutine(CardEffectCommons.AddThisCardToHand(selectedCards[0], activateClass));
+                    }
+                }
+            }
+
+            #endregion
+
+            #region Security
+
+            if (timing == EffectTiming.SecuritySkill)
+            {
+                cardEffects.Add(CardEffectFactory.PlaySelfTamerSecurityEffect(card));
+            }
+
+            #endregion
+
+            return cardEffects;
+        }
+    }
+}

+ 11 - 0
Assets/CardEffect/BT21/Black/BT21_087.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 284729a88a94a464fad628a763308073
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 321 - 0
Assets/CardEffect/BT21/Black/BT21_098.cs

@@ -0,0 +1,321 @@
+using System.Collections;
+using System.Collections.Generic;
+
+namespace DCGO.CardEffects.BT21
+{
+    //Ragnarok Cannon
+    public class BT21_098 : CEntity_Effect
+    {
+        public override List<ICardEffect> CardEffects(EffectTiming timing, CardSource card)
+        {
+            List<ICardEffect> cardEffects = new List<ICardEffect>();
+
+            #region Main
+
+            if (timing == EffectTiming.OptionSkill)
+            {
+                ActivateClass activateClass = new ActivateClass();
+                activateClass.SetUpICardEffect($"Delete 1 opponent's Digimon with lowest play cost and place in battle area.", CanUseCondition, card);
+                activateClass.SetUpActivateClass(null, ActivateCoroutine, -1, false, EffectDescription());
+                cardEffects.Add(activateClass);
+
+                string EffectDescription()
+                {
+                    return "[Main] Delete 1 of your opponent's Digimon with the lowest play cost. Then, place this card in the battle area.";
+                }
+
+                bool CanSelectPermanentCondition(Permanent permanent)
+                {
+                    return CardEffectCommons.IsPermanentExistsOnOpponentBattleAreaDigimon(permanent, card) &&
+                           CardEffectCommons.IsMinCost(permanent, card.Owner.Enemy, true);
+                }
+
+                bool CanUseCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.CanTriggerOptionMainEffect(hashtable, card);
+                }
+
+                IEnumerator ActivateCoroutine(Hashtable hashtable)
+                {
+                    if (CardEffectCommons.HasMatchConditionPermanent(CanSelectPermanentCondition))
+                    {
+                        SelectPermanentEffect selectPermanentEffect = GManager.instance.GetComponent<SelectPermanentEffect>();
+
+                        selectPermanentEffect.SetUp(
+                            selectPlayer: card.Owner,
+                            canTargetCondition: CanSelectPermanentCondition,
+                            canTargetCondition_ByPreSelecetedList: null,
+                            canEndSelectCondition: null,
+                            maxCount: 1,
+                            canNoSelect: false,
+                            canEndNotMax: false,
+                            selectPermanentCoroutine: null,
+                            afterSelectPermanentCoroutine: null,
+                            mode: SelectPermanentEffect.Mode.Destroy,
+                            cardEffect: activateClass);
+
+                        yield return ContinuousController.instance.StartCoroutine(selectPermanentEffect.Activate());
+
+                        yield return ContinuousController.instance.StartCoroutine(CardEffectCommons.PlaceDelayOptionCards(card: card, cardEffect: activateClass));
+                    }
+                }
+            }
+
+            #endregion
+
+            #region Your Turn Delay
+            if (timing == EffectTiming.OnDeclaration)
+            {
+                ActivateClass activateClass = new ActivateClass();
+                activateClass.SetUpICardEffect("Delete 1 opponent's Digimon with lowest play cost, trash security until 1 left if didn't delete", CanUseCondition, card);
+                activateClass.SetUpActivateClass(CanActivateCondition, ActivateCoroutine, -1, true, EffectDescription());
+                cardEffects.Add(activateClass);
+
+                string EffectDescription()
+                {
+                    return "[Your Turn] When one of your [Galacticmon] attacks, <Delay>.\n• Delete 1 of your opponent's Digimon with the lowest play cost. If this effect didn't delete, trash the top cards of your opponent's security stack so that is has 1 card left.";
+                }
+
+                bool PermanentCondition(Permanent permanent)
+                {
+                    if (CardEffectCommons.IsOwnerPermanent(permanent, card))
+                    {
+                        return permanent.TopCard.EqualsCardName("Galacticmon");
+                    }
+
+                    return false;
+                }
+
+                bool CanUseCondition(Hashtable hashtable)
+                {
+                    if (CardEffectCommons.IsExistOnBattleArea(card))
+                    {
+                        if (CardEffectCommons.CanTriggerOnPermanentAttack(hashtable, PermanentCondition))
+                        {
+                            if (CardEffectCommons.CanDeclareOptionDelayEffect(card))
+                            {
+                                return true;
+                            }
+                        }
+                    }
+
+                    return false;
+                }
+
+                bool CanActivateCondition(Hashtable hashtable)
+                {
+                    if (CardEffectCommons.IsExistOnBattleArea(card))
+                    {
+                        if (card.PermanentOfThisCard().CanBeDestroyedBySkill(activateClass))
+                        {
+                            return true;
+                        }
+                    }
+
+                    return false;
+                }
+
+                bool CanSelectPermanentCondition(Permanent permanent)
+                {
+                    return CardEffectCommons.IsPermanentExistsOnOpponentBattleAreaDigimon(permanent, card) &&
+                           CardEffectCommons.IsMinCost(permanent, card.Owner.Enemy, true);
+                }
+
+                IEnumerator ActivateCoroutine(Hashtable hashtable)
+                {
+                    List<Permanent> deleteTargetPermanents = new List<Permanent>();
+
+                    bool attemptedToDelete = false;
+
+                    if (CardEffectCommons.HasMatchConditionPermanent(CanSelectPermanentCondition))
+                    {
+                        SelectPermanentEffect selectPermanentEffect = GManager.instance.GetComponent<SelectPermanentEffect>();
+
+                        selectPermanentEffect.SetUp(
+                            selectPlayer: card.Owner,
+                            canTargetCondition: CanSelectPermanentCondition,
+                            canTargetCondition_ByPreSelecetedList: null,
+                            canEndSelectCondition: null,
+                            maxCount: 1,
+                            canNoSelect: false,
+                            canEndNotMax: false,
+                            selectPermanentCoroutine: null,
+                            afterSelectPermanentCoroutine: AfterSelectPermanentCoroutine,
+                            mode: SelectPermanentEffect.Mode.Destroy,
+                            cardEffect: activateClass);
+
+                        yield return ContinuousController.instance.StartCoroutine(selectPermanentEffect.Activate());
+
+                        IEnumerator AfterSelectPermanentCoroutine(List<Permanent> permanents)
+                        {
+                            deleteTargetPermanents = permanents.Clone();
+
+                            attemptedToDelete = true;
+
+                            yield return null;
+                        }
+                    }
+
+                    if (attemptedToDelete)
+                    {
+                        yield return ContinuousController.instance.StartCoroutine(CardEffectCommons.DeletePeremanentAndProcessAccordingToResult(targetPermanents: deleteTargetPermanents, activateClass: activateClass, successProcess: null, failureProcess: FailureProcess));
+
+                        IEnumerator FailureProcess()
+                        {
+                            yield return ContinuousController.instance.StartCoroutine(new IDestroySecurity(
+                                player: card.Owner.Enemy,
+                                destroySecurityCount: card.Owner.Enemy.SecurityCards.Count - 1,
+                                cardEffect: activateClass,
+                                fromTop: true).DestroySecurity());
+                        }
+                    }
+                    else
+                    {
+                        yield return ContinuousController.instance.StartCoroutine(new IDestroySecurity(
+                            player: card.Owner.Enemy,
+                            destroySecurityCount: card.Owner.Enemy.SecurityCards.Count - 1,
+                            cardEffect: activateClass,
+                            fromTop: true).DestroySecurity());
+                    }
+                }
+            }
+            #endregion
+
+            #region Security
+
+            if (timing == EffectTiming.SecuritySkill)
+            {
+                ActivateClass activateClass = new ActivateClass();
+                activateClass.SetUpICardEffect($"Play 1 card with [VEMMON] in text from hand or trash and add this card to hand", CanUseCondition, card);
+                activateClass.SetUpActivateClass(null, ActivateCoroutine, -1, true, EffectDescription());
+                activateClass.SetIsSecurityEffect(true);
+                cardEffects.Add(activateClass);
+
+                string EffectDescription()
+                {
+                    return
+                        "[Security] You may play 1 card with [Vemmon] in its text and a play cost of 6 or less from your hand or trash without paying the cost. Then, add this card to the hand.";
+                }
+
+                bool CanUseCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.CanTriggerSecurityEffect(hashtable, card);
+                }
+
+                bool CanSelectCardCondition(CardSource cardSource)
+                {
+                    return (cardSource.HasText("Vemmon")) &&
+                           cardSource.HasPlayCost &&
+                           cardSource.GetCostItself <= 6 &&
+                           CardEffectCommons.CanPlayAsNewPermanent(cardSource: cardSource, payCost: false, cardEffect: activateClass);
+                }
+
+                IEnumerator ActivateCoroutine(Hashtable hashtable)
+                {
+                    bool canSelectHand = CardEffectCommons.HasMatchConditionOwnersHand(card, CanSelectCardCondition);
+                    bool canSelectTrash = card.Owner.TrashCards.Some(CanSelectCardCondition);
+
+                    if (canSelectHand || canSelectTrash)
+                    {
+                        if (canSelectHand && canSelectTrash)
+                        {
+                            List<SelectionElement<bool>> selectionElements = new List<SelectionElement<bool>>
+                            {
+                                new(message: "From hand", value: true, spriteIndex: 0),
+                                new(message: "From trash", value: false, spriteIndex: 1),
+                            };
+
+                            string selectPlayerMessage = "From which area do you play a card?";
+                            string notSelectPlayerMessage = "The opponent is choosing from which area to play a card.";
+
+                            GManager.instance.userSelectionManager.SetBoolSelection(selectionElements: selectionElements,
+                                selectPlayer: card.Owner, selectPlayerMessage: selectPlayerMessage,
+                                notSelectPlayerMessage: notSelectPlayerMessage);
+                        }
+
+                        else
+                        {
+                            GManager.instance.userSelectionManager.SetBool(canSelectHand);
+                        }
+
+                        yield return ContinuousController.instance.StartCoroutine(GManager.instance.userSelectionManager
+                            .WaitForEndSelect());
+
+                        bool fromHand = GManager.instance.userSelectionManager.SelectedBoolValue;
+
+                        List<CardSource> selectedCards = new List<CardSource>();
+
+                        IEnumerator SelectCardCoroutine(CardSource cardSource)
+                        {
+                            selectedCards.Add(cardSource);
+                            yield return null;
+                        }
+
+                        if (fromHand)
+                        {
+                            SelectHandEffect selectHandEffect = GManager.instance.GetComponent<SelectHandEffect>();
+
+                            selectHandEffect.SetUp(
+                                selectPlayer: card.Owner,
+                                canTargetCondition: CanSelectCardCondition,
+                                canTargetCondition_ByPreSelecetedList: null,
+                                canEndSelectCondition: null,
+                                maxCount: 1,
+                                canNoSelect: true,
+                                canEndNotMax: false,
+                                isShowOpponent: true,
+                                selectCardCoroutine: SelectCardCoroutine,
+                                afterSelectCardCoroutine: null,
+                                mode: SelectHandEffect.Mode.Custom,
+                                cardEffect: activateClass);
+
+                            selectHandEffect.SetUpCustomMessage("Select 1 card to play.", "The opponent is selecting 1 card to play.");
+                            selectHandEffect.SetUpCustomMessage_ShowCard("Played Card");
+
+                            yield return StartCoroutine(selectHandEffect.Activate());
+                        }
+
+                        else
+                        {
+                            SelectCardEffect selectCardEffect = GManager.instance.GetComponent<SelectCardEffect>();
+
+                            selectCardEffect.SetUp(
+                                canTargetCondition: CanSelectCardCondition,
+                                canTargetCondition_ByPreSelecetedList: null,
+                                canEndSelectCondition: null,
+                                canNoSelect: () => true,
+                                selectCardCoroutine: SelectCardCoroutine,
+                                afterSelectCardCoroutine: null,
+                                message: "Select 1 card to play.",
+                                maxCount: 1,
+                                canEndNotMax: false,
+                                isShowOpponent: true,
+                                mode: SelectCardEffect.Mode.Custom,
+                                root: SelectCardEffect.Root.Trash,
+                                customRootCardList: null,
+                                canLookReverseCard: true,
+                                selectPlayer: card.Owner,
+                                cardEffect: activateClass);
+
+                            selectCardEffect.SetUpCustomMessage("Select 1 card to play.", "The opponent is selecting 1 card to play.");
+                            selectCardEffect.SetUpCustomMessage_ShowCard("Played Card");
+
+                            yield return ContinuousController.instance.StartCoroutine(selectCardEffect.Activate());
+                        }
+
+                        yield return ContinuousController.instance.StartCoroutine(CardEffectCommons.PlayPermanentCards(
+                            cardSources: selectedCards, activateClass: activateClass, payCost: false, isTapped: false,
+                            root: fromHand ? SelectCardEffect.Root.Hand : SelectCardEffect.Root.Trash,
+                            activateETB: true));
+                    }
+
+                    yield return ContinuousController.instance.StartCoroutine(CardEffectCommons.AddThisCardToHand(card, activateClass));
+                }
+            }
+
+            #endregion
+
+            return cardEffects;
+        }
+    }
+}

+ 11 - 0
Assets/CardEffect/BT21/Black/BT21_098.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 78aa32f95e98010499fe671a5c0017d1
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 382 - 0
Assets/CardEffect/BT21/White/BT21_101.cs

@@ -0,0 +1,382 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+// Gaiamon
+namespace DCGO.CardEffects.BT21
+{
+    public class BT21_101 : CEntity_Effect
+    {
+        public override List<ICardEffect> CardEffects(EffectTiming timing, CardSource card)
+        {
+            List<ICardEffect> cardEffects = new List<ICardEffect>();
+
+            #region Static Effects
+
+            #region App Fusion (Globemon & Charismon)
+
+            if (timing == EffectTiming.None)
+            {
+                AddAppFusionConditionClass addAppFusionConditionClass = new AddAppFusionConditionClass();
+                addAppFusionConditionClass.SetUpICardEffect($"App Fusion", (hashtable) => true, card);
+                addAppFusionConditionClass.SetUpAddAppFusionConditionClass(getAppFusionCondition: GetAppFusion);
+                addAppFusionConditionClass.SetNotShowUI(true);
+                cardEffects.Add(addAppFusionConditionClass);
+
+                AppFusionCondition GetAppFusion(CardSource cardSource)
+                {
+                    string selectLinkMessage = "";
+                    string selectDigimonMessage = "";
+                    bool linkCondition(CardSource source)
+                    {
+                        if (source != null)
+                        {
+                            if (source.PermanentOfThisCard().TopCard.EqualsCardName("Globemon"))
+                            {
+                                if (source.PermanentOfThisCard().LinkedCards.Find(x => x.EqualsCardName("Charismon")))
+                                {
+                                    selectLinkMessage = "1 [Charismon]";
+                                    return true;
+                                }
+                            }
+                            if (source.PermanentOfThisCard().TopCard.EqualsCardName("Charismon"))
+                            {
+                                if (source.PermanentOfThisCard().LinkedCards.Find(x => x.EqualsCardName("Globemon")))
+                                {
+                                    selectLinkMessage = "1 [Globemon]";
+                                    return true;
+                                }
+                            }
+                            return false;
+                        }
+
+                        return false;
+                    }
+                    bool digimonCondition(Permanent permanent)
+                    {
+                        if (CardEffectCommons.IsPermanentExistsOnOwnerBattleAreaDigimon(permanent, card))
+                        {
+                            if (permanent.TopCard.EqualsCardName("Globemon"))
+                            {
+                                if (permanent.LinkedCards.Find(x => x.EqualsCardName("Charismon")))
+                                {
+                                    selectDigimonMessage = "1 [Charismon]";
+                                    return true;
+                                }
+                            }
+                            if (permanent.TopCard.EqualsCardName("Charismon"))
+                            {
+                                if (permanent.LinkedCards.Find(x => x.EqualsCardName("Globemon")))
+                                {
+                                    selectDigimonMessage = "1 [Globemon]";
+                                    return true;
+                                }
+                            }
+                            return false;
+                        }
+
+                        return false;
+                    }
+
+                    if (cardSource == card)
+                    {
+                        AppFusionCondition AppFusionCondition = new AppFusionCondition(
+                            linkedCondition: linkCondition,
+                            selectLinkMessage: selectLinkMessage,
+                            digimonCondition: digimonCondition,
+                            selectDigimonMessage: selectDigimonMessage,
+                            cost: 0);
+
+                        return AppFusionCondition;
+                    }
+
+                    return null;
+                }
+            }
+
+            #endregion
+
+            #region Blocker
+
+            if (timing == EffectTiming.None) cardEffects.Add(CardEffectFactory.BlockerSelfStaticEffect(isInheritedEffect: false, card: card, condition: null));
+
+            #endregion
+
+            #region Link +1
+
+            if (timing == EffectTiming.None) cardEffects.Add(CardEffectFactory.ChangeSelfLinkMaxStaticEffect(card.PermanentOfThisCard().LinkedMax + 1, false, card, null));
+
+            #endregion
+
+            #endregion
+
+            #region YourTurn
+
+            if (timing == EffectTiming.WhenLinked)
+            {
+                ActivateClass activateClass = new ActivateClass();
+                activateClass.SetUpICardEffect("Unsuspend, trash top sec", CanUseCondition, card);
+                activateClass.SetUpActivateClass(CanActivateCondition, ActivateCoroutine, 1, true, EffectDiscription());
+                activateClass.SetHashString("BT21_101_WhenLinked");
+                cardEffects.Add(activateClass);
+
+                string EffectDiscription()
+                    => "[Your Turn] [Once Per Turn] When your Digimon get linked, by unsuspending this Digimon, trash your opponent's top security card.";
+
+                bool CanUseCondition(Hashtable hashtable)
+                    => CardEffectCommons.IsExistOnBattleAreaDigimon(card)
+                    && CardEffectCommons.IsOwnerTurn(card)
+                    && CardEffectCommons.CanTriggerWhenLinked(hashtable, PermanentCondition, cardSource => true)
+                    && card.PermanentOfThisCard().IsSuspended
+                    && CardEffectCommons.CanUnsuspend(card.PermanentOfThisCard());
+
+                bool PermanentCondition(Permanent permanent)
+                    => CardEffectCommons.IsPermanentExistsOnOwnerBattleAreaDigimon(permanent, card);
+
+                bool CanActivateCondition(Hashtable hashtable)
+                    => CardEffectCommons.IsExistOnBattleAreaDigimon(card);
+
+                IEnumerator ActivateCoroutine(Hashtable hashtable)
+                {
+                    bool unsuspended = false;
+                    SelectPermanentEffect selectPermanentEffect = GManager.instance.GetComponent<SelectPermanentEffect>();
+                    selectPermanentEffect.SetUp
+                        (
+                        card.Owner,
+                        permanent => CardEffectCommons.IsPermanentExistsOnBattleAreaDigimon(permanent) && permanent == card.PermanentOfThisCard(),
+                        null,
+                        null,
+                        1,
+                        true,
+                        false,
+                        SelectPermanentCoroutine,
+                        null,
+                        SelectPermanentEffect.Mode.UnTap,
+                        activateClass
+                        );
+                    IEnumerator SelectPermanentCoroutine(Permanent permanent)
+                    {
+                        if (permanent.IsSuspended) unsuspended = true;
+                        yield return null;
+                    }
+                    yield return ContinuousController.instance.StartCoroutine(selectPermanentEffect.Activate());
+
+                    if (unsuspended)
+                    {
+                        yield return ContinuousController.instance.StartCoroutine(new IDestroySecurity(
+                        player: card.Owner.Enemy,
+                        destroySecurityCount: 1,
+                        cardEffect: activateClass,
+                        fromTop: true).DestroySecurity());
+                    }
+                }
+            }
+
+            #endregion
+
+            #region WD/WA Shared
+
+            bool SharedCanActivateCondition(Hashtable hashtable)
+            {
+                if (CardEffectCommons.IsExistOnBattleAreaDigimon(card))
+                {
+                    return true;
+                }
+                return false;
+            }
+
+            bool CanSelectLinkCard(CardSource cardSource)
+            {
+                if (cardSource.HasAppmonTraits)
+                {
+                    return true;
+                }
+                return false;
+            }
+
+            bool CanSelectDigimon(Permanent permanent)
+            {
+                if (CardEffectCommons.IsPermanentExistsOnOwnerBattleAreaDigimon(permanent, card))
+                {
+                    return true;
+                }
+                return false;
+            }
+            IEnumerator SharedActivateCoroutine(Hashtable hashtable, ActivateClass activateClass)
+            {
+                if (CardEffectCommons.HasMatchConditionOwnersPermanent(card, CanSelectDigimon))
+                {
+                    Permanent selectedPermanent = null;
+                    int maxCount = Math.Min(1, CardEffectCommons.MatchConditionPermanentCount(CanSelectDigimon));
+                    SelectPermanentEffect selectPermanentEffect = GManager.instance.GetComponent<SelectPermanentEffect>();
+
+                    selectPermanentEffect.SetUp(
+                        selectPlayer: card.Owner,
+                        canTargetCondition: CanSelectDigimon,
+                        canTargetCondition_ByPreSelecetedList: null,
+                        canEndSelectCondition: null,
+                        maxCount: maxCount,
+                        canNoSelect: true,
+                        canEndNotMax: false,
+                        selectPermanentCoroutine: SelectPermanentCoroutine,
+                        afterSelectPermanentCoroutine: null,
+                        mode: SelectPermanentEffect.Mode.Custom,
+                        cardEffect: activateClass);
+
+                    selectPermanentEffect.SetUpCustomMessage("Select 1 digimon to add link", "The opponent is selecting 1 digimon to add link");
+                    yield return ContinuousController.instance.StartCoroutine(selectPermanentEffect.Activate());
+
+                    IEnumerator SelectPermanentCoroutine(Permanent permanent)
+                    {
+                        selectedPermanent = permanent;
+                        yield return null;
+                    }
+
+                    if (selectedPermanent != null)
+                    {
+                        List<SelectionElement<bool>> selectionElements = new List<SelectionElement<bool>>()
+                        {
+                            new SelectionElement<bool>(message: $"From This Digimon", value: true, spriteIndex: 0),
+                            new SelectionElement<bool>(message: $"From Hand", value: false, spriteIndex: 1),
+                        };
+
+                        string selectPlayerMessage = "Choose where to get the digimon from";
+                        string notSelectPlayerMessage = "The opponent is choosing effects.";
+
+                        GManager.instance.userSelectionManager.SetBoolSelection(
+                            selectionElements: selectionElements, selectPlayer: card.Owner,
+                            selectPlayerMessage: selectPlayerMessage,
+                            notSelectPlayerMessage: notSelectPlayerMessage);
+
+                        yield return ContinuousController.instance.StartCoroutine(GManager.instance
+                            .userSelectionManager.WaitForEndSelect());
+
+                        CardSource selectedCard = null;
+                        if (GManager.instance.userSelectionManager.SelectedBoolValue)
+                        {
+                            SelectCardEffect selectCardEffect = GManager.instance.GetComponent<SelectCardEffect>();
+                            selectCardEffect.SetUp(
+                                        canTargetCondition: CanSelectLinkCard,
+                                        canTargetCondition_ByPreSelecetedList: null,
+                                        canEndSelectCondition: null,
+                                        canNoSelect: () => true,
+                                        selectCardCoroutine: SelectCardCoroutine,
+                                        afterSelectCardCoroutine: null,
+                                        message: "Select 1 linked card.",
+                                        maxCount: 1,
+                                        canEndNotMax: false,
+                                        isShowOpponent: true,
+                                        mode: SelectCardEffect.Mode.Custom,
+                                        root: SelectCardEffect.Root.Custom,
+                                        customRootCardList: card.PermanentOfThisCard().LinkedCards,
+                                        canLookReverseCard: true,
+                                        selectPlayer: card.Owner,
+                                        cardEffect: activateClass);
+
+                            selectCardEffect.SetUpCustomMessage("Select 1 linked card to remove", "The opponent is selecting 1 linked card to remove");
+
+                            yield return StartCoroutine(selectCardEffect.Activate());
+
+                            IEnumerator SelectCardCoroutine(CardSource cardSource)
+                            {
+                                selectedCard = cardSource;
+                                card.PermanentOfThisCard().LinkedCards.Remove(cardSource);
+                                yield return null;
+                            }
+                        }
+                        else
+                        {
+                            SelectHandEffect selectHandEffect = GManager.instance.GetComponent<SelectHandEffect>();
+                            selectHandEffect.SetUp(
+                                        selectPlayer: card.Owner,
+                                        canTargetCondition: CanSelectLinkCard,
+                                        canTargetCondition_ByPreSelecetedList: null,
+                                        canEndSelectCondition: null,
+                                        maxCount: 1,
+                                        canNoSelect: true,
+                                        canEndNotMax: false,
+                                        isShowOpponent: true,
+                                        selectCardCoroutine: SelectCardCoroutine,
+                                        afterSelectCardCoroutine: null,
+                                        mode: SelectHandEffect.Mode.Custom,
+                                        cardEffect: activateClass);
+                            selectHandEffect.SetUpCustomMessage("Select 1 linked card to remove", "The opponent is selecting 1 linked card to remove");
+                            yield return StartCoroutine(selectHandEffect.Activate());
+                            IEnumerator SelectCardCoroutine(CardSource cardSource)
+                            {
+                                selectedCard = cardSource;
+                                yield return null;
+                            }
+                        }
+                        if (selectedCard != null)
+                        {
+                            // Might need to talk to mike about this, things possibly to add
+                            // if link condiiton for selectedCard is sucessful, ex: if it needs exact name or traits, does it meet them.
+                            // Perphaps may lead to link requirements being added to the card itself, instead of an effect.
+                            // if this method below (AddLinkCard), automatically handles if the link max is hit, and allows for owner to choose which link to discarded for new one.
+                            selectedPermanent.AddLinkCard(selectedCard, activateClass);
+                        }
+                    }
+                }
+            }
+
+            #endregion
+
+            #region When Digivolving
+
+            if (timing == EffectTiming.OnEnterFieldAnyone)
+            {
+                ActivateClass activateClass = new ActivateClass();
+                activateClass.SetUpICardEffect("Add new link to a digimon", CanUseCondition, card);
+                activateClass.SetUpActivateClass(SharedCanActivateCondition, (hashtable) => SharedActivateCoroutine(hashtable, activateClass), -1, true, EffectDiscription());
+                cardEffects.Add(activateClass);
+
+                string EffectDiscription()
+                    => "[When Digivolving] You may link 1 Digimon card with the [Appmon] trait from your hand or this Digimon's digivolution cards to 1 of your Digimon without paying the cost.";
+
+                bool CanUseCondition(Hashtable hashtable)
+                {
+                    if (CardEffectCommons.IsExistOnBattleAreaDigimon(card))
+                    {
+                        if (CardEffectCommons.CanTriggerWhenDigivolving(hashtable, card))
+                        {
+                            return true;
+                        }
+                    }
+                    return false;
+                }
+            }
+
+            #endregion
+
+            #region When Attacking
+
+            if (timing == EffectTiming.OnAllyAttack)
+            {
+                ActivateClass activateClass = new ActivateClass();
+                activateClass.SetUpICardEffect("Add new link to a digimon", CanUseCondition, card);
+                activateClass.SetUpActivateClass(SharedCanActivateCondition, (hashtable) => SharedActivateCoroutine(hashtable, activateClass), -1, true, EffectDiscription());
+                cardEffects.Add(activateClass);
+
+                string EffectDiscription()
+                    => "[When Attacking] You may link 1 Digimon card with the [Appmon] trait from your hand or this Digimon's digivolution cards to 1 of your Digimon without paying the cost.";
+
+                bool CanUseCondition(Hashtable hashtable)
+                {
+                    if (CardEffectCommons.IsExistOnBattleAreaDigimon(card))
+                    {
+                        if (CardEffectCommons.CanTriggerOnAttack(hashtable, card))
+                        {
+                            return true;
+                        }
+                    }
+                    return false;
+                }
+            }
+
+            #endregion
+
+            return cardEffects;
+        }
+    }
+}

+ 11 - 0
Assets/CardEffect/BT21/White/BT21_101.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 463c2bbb3b750a647b1aa867d2b1198c
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 142 - 0
Assets/CardEffect/BT21/White/BT21_102.cs

@@ -0,0 +1,142 @@
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+
+// Tai Kamiya
+namespace DCGO.CardEffects.BT21
+{
+    public class BT21_102 : CEntity_Effect
+    {
+        public override List<ICardEffect> CardEffects(EffectTiming timing, CardSource card)
+        {
+            List<ICardEffect> cardEffects = new List<ICardEffect>();
+
+            #region Start of Your Turn
+
+            if (timing == EffectTiming.OnStartTurn) cardEffects.Add(CardEffectFactory.SetMemoryTo3TamerEffect(card));
+
+            #endregion
+
+            #region Your Turn
+
+            if (timing == EffectTiming.OnAllyAttack)
+            {
+                ActivateClass activateClass = new ActivateClass();
+                activateClass.SetUpICardEffect("Suspend to draw 1", CanUseCondition, card);
+                activateClass.SetUpActivateClass(CanActivateCondition, ActivateCoroutine, -1, true, EffectDiscription());
+                cardEffects.Add(activateClass);
+
+                string EffectDiscription()
+                    => "When one of your Digimon attacks, by suspending this Tamer, <Draw 1>";
+
+                bool CanUseCondition(Hashtable hashtable)
+                    => CardEffectCommons.IsExistOnBattleArea(card)
+                    && CardEffectCommons.IsOwnerTurn(card)
+                    && CardEffectCommons.CanActivateSuspendCostEffect(card)
+                    && CardEffectCommons.CanTriggerOnPermanentAttack(hashtable, PermanentCondition);
+
+                bool PermanentCondition(Permanent permanent)
+                    => CardEffectCommons.IsPermanentExistsOnOwnerBattleAreaDigimon(permanent, card);
+
+                bool CanActivateCondition(Hashtable hashtable)
+                    => CardEffectCommons.IsExistOnBattleArea(card);
+
+                IEnumerator ActivateCoroutine(Hashtable hashtable)
+                {
+                    yield return ContinuousController.instance.StartCoroutine(new SuspendPermanentsClass(new List<Permanent>() { card.PermanentOfThisCard() }, CardEffectCommons.CardEffectHashtable(activateClass)).Tap());
+
+                    if (card.Owner.LibraryCards.Count >= 1)
+                    {
+                        yield return ContinuousController.instance.StartCoroutine(new DrawClass(card.Owner, 1, activateClass).Draw());
+                    }
+                }
+            }
+
+            #endregion
+
+            #region Main
+
+            if (timing == EffectTiming.OnDeclaration)
+            {
+                ActivateClass activateClass = new ActivateClass();
+                activateClass.SetUpICardEffect("Play Adventure/Hero Digimon for reduced cost", CanUseCondition, card);
+                activateClass.SetUpActivateClass(CanActivateCondition, ActivateCoroutine, 1, true, EffectDiscription());
+                activateClass.SetHashString("Play_BT21_102");
+                cardEffects.Add(activateClass);
+
+                string EffectDiscription()
+                    => "[Main] [Once Per Turn] You may play 1 [ADVENTURE]/[Hero] trait card with a play cost of 2 or less from your hand without paying the cost. For each of your Tamers' colors, add 1 to this effect's play cost maximum. Then, return this Tamer to the bottom of the deck.";
+
+                bool CanUseCondition(Hashtable hashtable)
+                    => CardEffectCommons.IsExistOnBattleArea(card)
+                    && CardEffectCommons.IsOwnerTurn(card)
+                    && CardEffectCommons.HasMatchConditionOwnersHand(card, CanSelectDigimon);
+
+                bool CanActivateCondition(Hashtable hashtable)
+                    => CardEffectCommons.IsExistOnBattleArea(card);
+
+                bool CanSelectDigimon(CardSource source)
+                    => source.IsDigimon
+                    && source.BasePlayCostFromEntity <= AdjustedPlayCostMax(source)
+                    && (source.HasAdventureTraits || source.HasHeroTraits);
+
+                int AdjustedPlayCostMax(CardSource cardSource)
+                {
+                    var tamers = cardSource.Owner.GetBattleAreaPermanents().Filter(x => x.IsTamer).Select(x => x.TopCard).ToList();
+                    return 2 + Combinations.GetDifferenetColorCardCount(tamers);
+                }
+
+                IEnumerator ActivateCoroutine(Hashtable hashtable)
+                {
+                    SelectHandEffect selectHandEffect = GManager.instance.GetComponent<SelectHandEffect>();
+                    selectHandEffect.SetUp(
+                        selectPlayer: card.Owner,
+                        canTargetCondition: CanSelectDigimon,
+                        canTargetCondition_ByPreSelecetedList: null,
+                        canEndSelectCondition: null,
+                        maxCount: 1,
+                        canNoSelect: true,
+                        canEndNotMax: false,
+                        isShowOpponent: true,
+                        selectCardCoroutine: SelectCardCoroutine,
+                        afterSelectCardCoroutine: null,
+                        mode: SelectHandEffect.Mode.Custom,
+                        cardEffect: activateClass);
+
+                    selectHandEffect.SetUpCustomMessage("Select 1 digimon to play.",
+                        "The opponent is selecting 1 digimon to play.");
+                    selectHandEffect.SetUpCustomMessage_ShowCard("Played Card");
+
+                    yield return StartCoroutine(selectHandEffect.Activate());
+
+                    IEnumerator SelectCardCoroutine(CardSource cardSource)
+                    {
+                        yield return ContinuousController.instance.StartCoroutine(CardEffectCommons.PlayPermanentCards(
+                            cardSources: new List<CardSource>() { cardSource },
+                            activateClass: activateClass,
+                            payCost: false,
+                            isTapped: false,
+                            root: SelectCardEffect.Root.Hand,
+                            activateETB: true,
+                            isBreedingArea: false
+                        ));
+                    }
+
+                    var cardSources = new List<CardSource>() { card };
+                    yield return ContinuousController.instance.StartCoroutine(CardObjectController.AddLibraryBottomCards(cardSources));
+                    yield return ContinuousController.instance.StartCoroutine(GManager.instance.GetComponent<Effects>().ShowCardEffect2(cardSources, "Deck Bottom Cards", true, true));
+                }
+            }
+
+            #endregion
+
+            #region Security
+
+            if (timing == EffectTiming.SecuritySkill) cardEffects.Add(CardEffectFactory.PlaySelfTamerSecurityEffect(card));
+
+            #endregion
+
+            return cardEffects;
+        }
+    }
+}

+ 11 - 0
Assets/CardEffect/BT21/White/BT21_102.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 1689fc9e5aa4efd4c84fb4bd9c958e8a
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 0 - 1
Assets/Editor/JSONLoader_CardEntity.cs

@@ -152,7 +152,6 @@ namespace DCGO.CardEntities
             cardEntity.LinkDP = dpParse(card.linkDP);
             cardEntity.LinkEffect = card.linkEffect;
             cardEntity.LinkRequirement = card.linkRequirement;
-            cardEntity.LinkCost = GetLinkCost(card.linkRequirement);
 
             cardEntity.name = cardEntity.CardSpriteName.Replace("-Errata","").Replace("-","_");
 

+ 0 - 1
Assets/Scripts/CEntity_Base.cs

@@ -35,7 +35,6 @@ public class CEntity_Base : ScriptableObject
     public int LinkDP = 0;
     [TextArea] public string LinkEffect = "";
     [TextArea] public string LinkRequirement = "";
-    public int LinkCost = 0;
 
     public bool HasInhetitedEffect => !string.IsNullOrEmpty(InheritedEffectDiscription_ENG) && !InheritedEffectDiscription_ENG.Equals("-");
     public bool HasSecutiryEffect => !string.IsNullOrEmpty(SecurityEffectDiscription_ENG) && !SecurityEffectDiscription_ENG.Equals("-");

+ 0 - 7
Assets/Scripts/CardEffectCommons/GameContextDeterminarion.cs

@@ -526,11 +526,4 @@ public partial class CardEffectCommons
     }
 
     #endregion
-
-    #region Get multi colour count from permanents in owners battle area
-
-    public static int GetColourCountOnOwnerBattleArea(CardSource card, Func<Permanent, bool> canGetCardColour) =>
-        card.Owner.GetBattleAreaPermanents().Filter(x => canGetCardColour(x)).ToList().Count;
-
-    #endregion
 }

+ 96 - 0
Assets/Scripts/CardEffectFactory/AddLinkRequirement.cs

@@ -0,0 +1,96 @@
+using System.Collections;
+using System.Collections.Generic;
+using System;
+using System.Linq;
+using UnityEngine;
+using System.Net.NetworkInformation;
+
+public partial class CardEffectFactory
+{
+    #region Static effect that adds one's own card's link condition
+    public static AddLinkConditionClass AddSelfLinkConditionStaticEffect(Func<Permanent, bool> permanentCondition, int linkCost, CardSource card, Func<bool> condition = null, Func<CardSource, bool> cardCondition = null, string effectName = null)
+    {
+        bool CanUseCondition()
+        {
+            return condition == null || condition();
+        }
+
+        return AddLinkConditionStaticEffect(
+            permanentCondition: permanentCondition,
+            cardCondition: cardCondition ?? ((cardSource) => cardSource == card),
+            linkCost: linkCost,
+            isInheritedEffect: false,
+            card: card,
+            condition: CanUseCondition,
+            effectName: effectName ?? "Link");
+    }
+    #endregion
+
+    #region Static effect that adds link condition
+    public static AddLinkConditionClass AddLinkConditionStaticEffect(Func<Permanent, bool> permanentCondition, Func<CardSource, bool> cardCondition, int linkCost, bool isInheritedEffect, CardSource card, Func<bool> condition, string effectName)
+    {
+        AddLinkConditionClass addLinkConditionClass = new AddLinkConditionClass();
+        addLinkConditionClass.SetUpICardEffect(effectName, CanUseCondition, card);
+        addLinkConditionClass.SetUpAddLinkConditionClass(getLinkCondition: GetLink);
+
+        if (isInheritedEffect)
+            addLinkConditionClass.SetIsInheritedEffect(true);
+
+        bool CanUseCondition(Hashtable hashtable)
+        {
+            return condition == null || condition();
+        }
+
+        bool CardCondition(CardSource cardSource)
+        {
+            if (cardSource != null)
+            {
+                if (cardCondition == null || cardCondition(cardSource))
+                {
+                    return true;
+                }
+            }
+
+            return false;
+        }
+
+        bool PermanentCondition(Permanent permanent)
+        {
+            if (permanent != null)
+            {
+                if (permanent.TopCard != null)
+                {
+                    if (permanentCondition == null || permanentCondition(permanent))
+                    {
+                        return true;
+                    }
+                }
+            }
+
+            return false;
+        }
+
+        LinkCondition GetLink(CardSource cardSource)
+        {
+            if (cardSource == card)
+            {
+                if (CardCondition(cardSource)){
+                    LinkCondition LinkCondition = new LinkCondition(
+                                        digimonCondition: PermanentCondition,
+                                        cost: linkCost);
+
+                    return LinkCondition;
+                }
+            }
+
+            return null;
+        }
+
+        
+
+        
+
+        return addLinkConditionClass;
+    }
+    #endregion
+}

+ 11 - 0
Assets/Scripts/CardEffectFactory/AddLinkRequirement.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: e0644b033bc5e4844a1afc6f82d2a20d
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 3 - 3
Assets/Scripts/CardEffectFactory/KeyWordEffects/Link.cs

@@ -16,7 +16,7 @@ public partial class CardEffectFactory
     /// <param name="Func(bool)">condition for you to be able to link</param>
     /// <param name="Func(Permanent,bool)">Any permaent condtion for you to link to</param>
     /// <author>Mike Bunch</author>
-    public static ActivateClass LinkEffect(CardSource card, Func<Permanent, bool> digimonCondition, Func<bool> condition = null)
+    public static ActivateClass LinkEffect(CardSource card, Func<bool> condition = null)
     {
         if (card == null) return null;
         if (!CardEffectCommons.IsOwnerTurn(card)) return null;
@@ -33,7 +33,7 @@ public partial class CardEffectFactory
             {
                 if(permanent != card.PermanentOfThisCard())
                 {
-                    if (digimonCondition == null || digimonCondition(permanent))
+                    if (card.linkCondition == null || card.linkCondition.digimonCondition(permanent))
                     {
                         return true;
                     }
@@ -62,7 +62,7 @@ public partial class CardEffectFactory
         IEnumerator ActivateCoroutine(Hashtable _hashtable)
         {
 
-            yield return ContinuousController.instance.StartCoroutine(card.Owner.AddMemory(card.LinkCost, activateClass));
+            yield return ContinuousController.instance.StartCoroutine(card.Owner.AddMemory(card.linkCondition.cost, activateClass));
 
             Permanent selectedPermanent = null;
 

+ 7 - 0
Assets/Scripts/CardEffectInterfaces.cs

@@ -385,6 +385,13 @@ public interface IAddBurstDigivolutionConditionEffect
 }
 #endregion
 
+#region "Target card gains Link conditions" effect
+public interface IAddLinkConditionEffect
+{
+    LinkCondition GetLinkCondition(CardSource cardSource);
+}
+#endregion
+
 #region "Target card gains App Fusion digivolution conditions" effect
 public interface IAddAppFusionConditionEffect
 {

+ 27 - 0
Assets/Scripts/CardEffects/AddLinkConditionClass.cs

@@ -0,0 +1,27 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using System;
+public class AddLinkConditionClass : ICardEffect, IAddLinkConditionEffect
+{
+    Func<CardSource, LinkCondition> _getLinkCondition { get; set; }
+    public void SetUpAddLinkConditionClass(Func<CardSource, LinkCondition> getLinkCondition)
+    {
+        _getLinkCondition = getLinkCondition;
+    }
+    public LinkCondition GetLinkCondition(CardSource cardSource)
+    {
+        if (cardSource != null)
+        {
+            if (_getLinkCondition != null)
+            {
+                if (_getLinkCondition(cardSource) != null)
+                {
+                    return _getLinkCondition(cardSource);
+                }
+            }
+        }
+
+        return null;
+    }
+}

+ 11 - 0
Assets/Scripts/CardEffects/AddLinkConditionClass.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 07daea2001155fa4ca6f1bbb0a0cbe53
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 189 - 59
Assets/Scripts/CardSource.cs

@@ -253,7 +253,7 @@ public class CardSource : MonoBehaviour
     #region Permanent in the field containing this card
     public Permanent PermanentOfThisCard()
     {
-        return Owner.GetFieldPermanents().Find(permanent => 
+        return Owner.GetFieldPermanents().Find(permanent =>
             (permanent.cardSources.Contains(this)) && !IsFlipped);
     }
     #endregion
@@ -348,10 +348,6 @@ public class CardSource : MonoBehaviour
     public List<EvoCost> BaseEvoCostsFromEntity => _cEntity_Base.EvoCosts;
     #endregion
 
-    #region Link Cost
-    public int LinkCost => _cEntity_Base.LinkCost;
-    #endregion
-
     #region evoCosts
     public List<Func<Permanent, int>> EvoCosts(CardEffectCommons.IgnoreRequirement ignore, bool checkAvailability)
     {
@@ -406,7 +402,7 @@ public class CardSource : MonoBehaviour
                     .Map<EvoCost, Func<Permanent, int>>(evoCost =>
                     (targetPermanent) =>
                     {
-                        if(ignore.Equals(CardEffectCommons.IgnoreRequirement.All) && Owner.CanIgnoreDigivolutionRequirement(targetPermanent, this))
+                        if (ignore.Equals(CardEffectCommons.IgnoreRequirement.All) && Owner.CanIgnoreDigivolutionRequirement(targetPermanent, this))
                             return evoCost.MemoryCost;
 
                         if ((ignore.Equals(CardEffectCommons.IgnoreRequirement.Color) && Owner.CanIgnoreDigivolutionRequirement(targetPermanent, this))
@@ -432,7 +428,7 @@ public class CardSource : MonoBehaviour
     {
         CardEffectCommons.IgnoreRequirement ignore = CardEffectCommons.IgnoreRequirement.None;
 
-        if(ignoreLevel)
+        if (ignoreLevel)
             ignore = CardEffectCommons.IgnoreRequirement.Level;
 
         return EvoCosts(ignore, checkAvailability)
@@ -528,7 +524,7 @@ public class CardSource : MonoBehaviour
     #endregion
 
     #region get card cost of itself (refered by card effects)
-    public int GetCostItself => Math.Max(0, GetChangedCostItselef(BasePlayCostFromEntity, SelectCardEffect.Root.None, new List<Permanent>() { PermanentOfThisCard()}));
+    public int GetCostItself => Math.Max(0, GetChangedCostItselef(BasePlayCostFromEntity, SelectCardEffect.Root.None, new List<Permanent>() { PermanentOfThisCard() }));
     #endregion
 
     #region get card cost of itself taking into account card effects
@@ -611,7 +607,7 @@ public class CardSource : MonoBehaviour
     }
     #endregion
 
-        #region get card cost to pay of itself taking into account card effects
+    #region get card cost to pay of itself taking into account card effects
     public int GetChangedPayingCost(int Cost, SelectCardEffect.Root root, List<Permanent> targetPermanents, bool checkAvailability = false)
     {
         #region card effects that changes card cost to pay
@@ -1408,7 +1404,7 @@ public class CardSource : MonoBehaviour
                 return true;
             }
 
-            if(ContainsTraits("SeaAnimal"))
+            if (ContainsTraits("SeaAnimal"))
             {
                 return true;
             }
@@ -1417,7 +1413,7 @@ public class CardSource : MonoBehaviour
         }
     }
     #endregion
-    
+
     #region whether this card has at least 1 trait that contains "Angel"
     public bool HasAngelTraits
     {
@@ -1427,37 +1423,37 @@ public class CardSource : MonoBehaviour
             {
                 return true;
             }
-            
+
             if (ContainsTraits("Cherub"))
             {
                 return true;
             }
-            
+
             if (ContainsTraits("Throne"))
             {
                 return true;
             }
-            
+
             if (ContainsTraits("Authority"))
             {
                 return true;
             }
-            
+
             if (ContainsTraits("Seraph"))
             {
                 return true;
             }
-            
+
             if (ContainsTraits("Virtue"))
             {
                 return true;
             }
-            
+
             return false;
         }
     }
     #endregion
-    
+
     #region whether this card has 1 of the "Angel", "Archangel" or "Three Great Angels" trait
     public bool HasAngelTraitRestrictive
     {
@@ -1467,13 +1463,13 @@ public class CardSource : MonoBehaviour
             {
                 return true;
             }
-            
+
             if (ContainsTraits("Archangel"))
             {
                 return true;
             }
-            
-            if (CardTraits.Count(trait => 
+
+            if (CardTraits.Count(trait =>
                     (trait.Contains("Angel") || trait.Contains("angel"))
                     && trait != "Archangel"
                     && trait != "Fallen Angel" && trait != "FallenAngel"
@@ -1481,7 +1477,7 @@ public class CardSource : MonoBehaviour
             {
                 return true;
             }
-            
+
             return false;
         }
     }
@@ -1588,7 +1584,7 @@ public class CardSource : MonoBehaviour
                 return true;
             }
 
-            if(ContainsTraits("Beast Dragon"))
+            if (ContainsTraits("Beast Dragon"))
             {
                 return true;
             }
@@ -1597,7 +1593,7 @@ public class CardSource : MonoBehaviour
         }
     }
     #endregion
-    
+
     #region whether this card has at least 1 trait that contains "DigiPolice"
     public bool HasDigiPoliceTraits
     {
@@ -1607,15 +1603,15 @@ public class CardSource : MonoBehaviour
             {
                 return true;
             }
-            
+
             return false;
         }
     }
     #endregion
-    
+
     #region whether this card has at least 1 trait that contains "Light Fang" or "Night Claw"
     public bool HasLightFangNightClawTraits => ContainsTraits("Light Fang") || ContainsTraits("Night Claw");
-    
+
     #endregion
 
     #region whether this card has at least 1 trait that contains "Light Fang/Night Claw"
@@ -1661,11 +1657,12 @@ public class CardSource : MonoBehaviour
         foreach (string attribute in _cEntity_Base.Type_ENG)
             checkStrings.Add(DataBase.ReplaceToASCII(attribute));
 
-        if(jogressCondition != null){
+        if (jogressCondition != null)
+        {
             foreach (JogressConditionElement element in jogressCondition.elements)
                 checkStrings.Add(element.SelectMessage);
         }
-        
+
 
         foreach (string checkString in checkStrings)
         {
@@ -1691,11 +1688,11 @@ public class CardSource : MonoBehaviour
         return false;
     }
     #endregion
-    
+
     #region whether this card has <Save> in text
     public bool HasSaveText => HasText("<Save>");
     #endregion
-    
+
     #region whether this card has "Pulsemon" in text
     public bool HasPulsemonText => HasText("Pulsemon");
     #endregion
@@ -1980,7 +1977,7 @@ public class CardSource : MonoBehaviour
     #region whether this card has [Blocker]
     public bool HasBlocker =>
         EffectList(EffectTiming.None)
-            .Some(cardEffect => cardEffect is BlockerClass 
+            .Some(cardEffect => cardEffect is BlockerClass
                 && !cardEffect.IsInheritedEffect && !cardEffect.IsSecurityEffect);
     #endregion
 
@@ -2136,6 +2133,24 @@ public class CardSource : MonoBehaviour
     }
     #endregion
 
+    #region Link requirement
+    public LinkCondition linkCondition
+    {
+        get
+        {
+            ICardEffect addLinkConditonEffect =
+            EffectList(EffectTiming.None)
+            .Find(cardEffect => cardEffect is IAddLinkConditionEffect
+                && cardEffect.CanUse(null)
+                && ((IAddLinkConditionEffect)cardEffect).GetLinkCondition(this) != null);
+
+            if (addLinkConditonEffect != null) return ((IAddLinkConditionEffect)addLinkConditonEffect).GetLinkCondition(this);
+
+            return null;
+        }
+    }
+    #endregion
+
     #region whether this card can DNA digivolve
     public bool CanPlayJogress(bool PayCost)
     {
@@ -2277,35 +2292,35 @@ public class CardSource : MonoBehaviour
     #region whether this card has level
     public bool HasLevel => _cEntity_Base == null || _cEntity_Base.HasLevel;
     #endregion
-    
+
     #region whether this card is level 2
-    
+
     public bool IsLevel2 => (_cEntity_Base == null || _cEntity_Base.HasLevel) && _cEntity_Base.Level == 2;
-    
+
     #endregion
-    
+
     #region whether this card is level 3
-    
+
     public bool IsLevel3 => (_cEntity_Base == null || _cEntity_Base.HasLevel) && _cEntity_Base.Level == 3;
-    
+
     #endregion
-    
+
     #region whether this card is level 4
-    
+
     public bool IsLevel4 => (_cEntity_Base == null || _cEntity_Base.HasLevel) && _cEntity_Base.Level == 4;
-    
+
     #endregion
-    
+
     #region whether this card is level 5
-    
+
     public bool IsLevel5 => (_cEntity_Base == null || _cEntity_Base.HasLevel) && _cEntity_Base.Level == 5;
-    
+
     #endregion
-    
+
     #region whether this card is level 6
-    
+
     public bool IsLevel6 => (_cEntity_Base == null || _cEntity_Base.HasLevel) && _cEntity_Base.Level == 6;
-    
+
     #endregion
 
     #region DigiXros requirement
@@ -2449,6 +2464,40 @@ public class CardSource : MonoBehaviour
     }
     #endregion
 
+    #region whether this card can Link
+    public bool CanLink(bool PayCost)
+    {
+        if (linkCondition != null)
+        {
+            if (PayCost)
+            {
+                int cost = linkCondition.cost;
+
+                if (Owner.MaxMemoryCost < cost)
+                {
+                    return false;
+                }
+            }
+
+            if (Owner.GetBattleAreaDigimons().Count >= 1)
+            {
+                foreach (Permanent digimon in Owner.GetFieldPermanents())
+                {
+                    if (digimon != null)
+                    {
+                        if (linkCondition.digimonCondition(digimon))
+                        {
+                            return true;
+                        }
+                    }
+                }
+            }
+        }
+
+        return false;
+    }
+    #endregion
+
     #region whether this card can App Fusion
     public bool CanPlayAppFusion(bool PayCost)
     {
@@ -2476,21 +2525,11 @@ public class CardSource : MonoBehaviour
                         {
                             if (appFusionCondition.digimonCondition(digimon))
                             {
-                                foreach(CardSource linkedCard in digimon.LinkedCards)
+                                foreach (CardSource linkedCard in digimon.LinkedCards)
                                 {
                                     if (appFusionCondition.linkedCondition(linkedCard))
                                     {
-                                        if (PayCost)
-                                        {
-                                            int cost = appFusionCondition.cost;
-
-                                            cost = GetChangedCostItselef(cost, SelectCardEffect.Root.Hand, new List<Permanent>() { digimon }, checkAvailability: true);
-
-                                            if (Owner.MaxMemoryCost < cost)
-                                            {
-                                                return false;
-                                            }
-                                        }
+                                        return true;
                                     }
                                 }
                             }
@@ -2558,6 +2597,53 @@ public class CardSource : MonoBehaviour
     }
     #endregion
 
+    #region whether target permanent can Link into this card
+    public bool CanLinkFromTargetPermanent(Permanent targetPermanent, bool PayCost)
+    {
+        if (targetPermanent != null)
+        {
+            if (targetPermanent.TopCard != null)
+            {
+                if (targetPermanent.TopCard.Owner.GetFieldPermanents().Contains(targetPermanent))
+                {
+                    if (this.CanLink(PayCost))
+                    {
+                        if (linkCondition != null)
+                        {
+                            if (!this.CanNotEvolve(targetPermanent))
+                            {
+                                if (appFusionCondition.digimonCondition(targetPermanent))
+                                {
+                                    foreach (CardSource linkedCard in targetPermanent.LinkedCards)
+                                    {
+                                        if (appFusionCondition.linkedCondition(linkedCard))
+                                        {
+                                            if (PayCost)
+                                            {
+                                                int cost = appFusionCondition.cost;
+
+                                                cost = GetChangedCostItselef(cost, SelectCardEffect.Root.Hand, new List<Permanent>() { targetPermanent }, checkAvailability: true);
+
+                                                if (Owner.MaxMemoryCost < cost)
+                                                {
+                                                    return false;
+                                                }
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        return false;
+    }
+    #endregion
+
+
     #region whether target permanent can App Fusion into this card
     public bool CanAppFusionFromTargetPermanent(Permanent targetPermanent, bool PayCost)
     {
@@ -2746,6 +2832,22 @@ public class CardSource : MonoBehaviour
 
     #endregion
 
+    #region whether this card has "Hero" trait
+
+    public bool HasHeroTraits
+    {
+        get
+        {
+            if (CardTraits.Contains("Hero"))
+            {
+                return true;
+            }
+            return false;
+        }
+    }
+
+    #endregion
+
     #region whether this card has "Chronicle" trait
 
     public bool HasChronicleTraits
@@ -2813,6 +2915,23 @@ public class CardSource : MonoBehaviour
     }
 
     #endregion
+
+    #region whether this card has "Appmon" trait
+
+    public bool HasAppmonTraits
+    {
+        get
+        {
+            if (CardTraits.Find(x => x.Equals("Appmon")) != null)
+            {
+                return true;
+            }
+
+            return false;
+        }
+    }
+
+    #endregion
 }
 
 public class JogressCondition
@@ -2911,6 +3030,17 @@ public class BurstDigivolutionCondition
     public int cost { get; private set; } = 0;
 }
 
+public class LinkCondition
+{
+    public LinkCondition(Func<Permanent, bool> digimonCondition, int cost)
+    {
+        this.digimonCondition = digimonCondition;
+        this.cost = cost;
+    }
+    public Func<Permanent, bool> digimonCondition { get; private set; } = null;
+    public int cost { get; private set; } = 0;
+}
+
 public class AppFusionCondition
 {
     public AppFusionCondition(Func<CardSource, bool> linkedCondition, string selectLinkMessage, Func<Permanent, bool> digimonCondition, string selectDigimonMessage, int cost)

+ 28 - 19
Assets/Scripts/Effect Examples/Link_Examples.cs

@@ -10,30 +10,39 @@ namespace DCGO.CardEffects.Examples
         {
             List<ICardEffect> cardEffects = new List<ICardEffect>();
 
-            #region Basic link effect keyword
-            if (timing == EffectTiming.OnDeclaration)
+            #region Link Condition
+            if (timing == EffectTiming.None)
             {
-                //conditions for the permanent to link to
-                bool PermanentCondition(Permanent permanent)
+                static bool PermanentCondition(Permanent targetPermanent)
                 {
-                    if (CardEffectCommons.IsPermanentExistsOnBattleAreaDigimon(permanent))
-                    {
-                        if (permanent.TopCard.EqualsTraits("Appmon"))
-                        {
-                            return true;
-                        }
-                    }
-
-                    return false;
+                    return targetPermanent.TopCard.HasAppmonTraits;
                 }
 
-                //any conditions for being able to link (currently there are none but situations could arise) - OPTIONAL
-                bool Condition()
-                {
-                    return true;
-                }
+                /// <summary>
+                /// Used to add a link condition to itself
+                /// </summary>
+                /// <param name="permanentCondition">Function to check for target permanent conditions</param>
+                /// <param name="linkCost">Cost to perform link</param>
+                /// <param name="card">Reference to this card</param>
+                /// <param name="condition">OPTIONAL - Function to check for effect conditions</param>
+                /// <param name="cardCondition">OPTIONAL - Function to check for cards conditions</param>
+                /// <param name="effectName">OPTIONAL - name to show for effect (default "Link")</param>
+                /// <author>Mike Bunch</author>
+                cardEffects.Add(CardEffectFactory.AddSelfLinkConditionStaticEffect(permanentCondition: PermanentCondition, linkCost: 0, card: card));
+            }
 
-                cardEffects.Add(CardEffectFactory.LinkEffect(card, PermanentCondition, Condition));
+            #endregion
+
+            #region Basic link effect keyword
+            if (timing == EffectTiming.OnDeclaration)
+            {
+                /// <summary>
+                /// Used to link a card
+                /// </summary>
+                /// <param name="card">Reference to this card</param>
+                /// <param name="condition">OPTIONAL - Function to check for effect conditions</param>
+                /// <author>Mike Bunch</author>
+                cardEffects.Add(CardEffectFactory.LinkEffect(card));
             }
             #endregion
 

+ 49 - 1
Assets/Scripts/TurnStateMachine.cs

@@ -2241,7 +2241,7 @@ public class TurnStateMachine : MonoBehaviourPunCallbacks
                                                     }
 
                                                     //Normal evolution and burst evolution possible
-                                                    else if (canNormalDigivolution && !canJogressDigivolution && canBurstDigivolution)
+                                                    else if (canNormalDigivolution && !canJogressDigivolution && canBurstDigivolution && !canAppFusion)
                                                     {
                                                         Vector3 Pos = handCard.transform.position;
 
@@ -2288,6 +2288,54 @@ public class TurnStateMachine : MonoBehaviourPunCallbacks
                                                             }
                                                         }
                                                     }
+                                                    //Normal evolution and App Fusion possible
+                                                    else if (canNormalDigivolution && !canJogressDigivolution && !canBurstDigivolution && canAppFusion)
+                                                    {
+                                                        Vector3 Pos = handCard.transform.position;
+
+                                                        ResetUI();
+
+                                                        handCard.transform.GetChild(0).gameObject.SetActive(false);
+
+                                                        handCard.GetComponent<Draggable_HandCard>().ReturnDefaultPosition();
+
+                                                        StartCoroutine(SelectWheterToAppFusion());
+
+                                                        IEnumerator SelectWheterToAppFusion()
+                                                        {
+                                                            isSync = true;
+
+                                                            yield return ContinuousController.instance.StartCoroutine(GManager.instance.GetComponent<Effects>().MoveToExecuteCardEffect_SetPosition(handCard.cardSource, Pos));
+                                                            handCard.transform.position = handCard.cardSource.Owner.brainStormObject.BrainStormHandCards[0].transform.position;
+
+                                                            GManager.instance.selectAppFusionEffect.SetUp_SelectWheterToAppFusion
+                                                                (card: handCard.cardSource,
+                                                                evoRoot: fieldCardFrame.GetFramePermanent().TopCard,
+                                                                canNoSelect: true,
+                                                                endSelectCoroutine_Digivolve: _Digivolution,
+                                                                endSelectCoroutine_AppFusion: _SelectAppFusionPermanents,
+                                                                noSelectCoroutine: _NoSelectCoroutine);
+
+                                                            yield return ContinuousController.instance.StartCoroutine(GManager.instance.selectAppFusionEffect.SelectWheterToAppFusion());
+
+                                                            IEnumerator _Digivolution()
+                                                            {
+                                                                yield return null;
+                                                                Digivolution();
+                                                            }
+
+                                                            IEnumerator _SelectAppFusionPermanents()
+                                                            {
+                                                                yield return null;
+                                                                SelectAppFusionCards(false);
+                                                            }
+
+                                                            IEnumerator _NoSelectCoroutine()
+                                                            {
+                                                                yield return StartCoroutine(Return());
+                                                            }
+                                                        }
+                                                    }
 
                                                     #region Select Jogress evolution source
                                                     void SelectJogressDigivolutionCards(bool move)