Explorar el Código

Implement BT24-004, When would Link, and Link cost Reduction

hooperk hace 4 meses
padre
commit
0f34aceb02

+ 99 - 0
Assets/Scripts/CardEffect/BT25/Green/BT25_004.cs

@@ -0,0 +1,99 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+
+// Tapmon
+namespace DCGO.CardEffects.BT25
+{
+    public class BT25_004 : CEntity_Effect
+    {
+        
+        public override List<ICardEffect> CardEffects(EffectTiming timing, CardSource card)
+        {
+            List<ICardEffect> cardEffects = new List<ICardEffect>();
+
+            #region Shared Conditions
+
+            bool CardCondition(CardSource cardSource)
+            {
+                return cardSource.EqualsTraits("Social")
+                    || cardSource.EqualsTraits("Tool")
+                    || cardSource.EqualsTraits("Game");
+            }
+
+            bool PermanentCondition(Permanent permanent) => permanent == card.PermanentOfThisCard();
+
+            bool RootCondition(SelectCardEffect.Root root) => true;
+
+            bool isUpDown() => true;
+
+            int reducedCost = 1;
+
+            #endregion
+
+            #region Reduce Link Cost
+            if (timing == EffectTiming.BeforePayCost)
+            {
+                ActivateClass activateClass = new ();
+                activateClass.SetUpICardEffect("May reduce Link cost by 1", CanUseCondition, card);
+                activateClass.SetUpActivateClass(CanActivateCondition, ActivateCoroutine, 1, true, EffectDiscription());
+                activateClass.SetIsInheritedEffect(true);
+                activateClass.SetHashString("BT25_004_YT");
+                cardEffects.Add(activateClass);
+
+                string EffectDiscription()
+                {
+                    return "[Your Turn] [Once Per Turn] When a [Social], [Tool] or [Game] trait card would link to this Digimon, you may reduce the cost by 1.";
+                }
+
+                bool CanUseCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.IsExistOnBattleArea(card)
+                        && CardEffectCommons.CanTriggerWhenWouldLink(hashtable, CardCondition, PermanentCondition)
+                        && CardEffectCommons.IsOwnerTurn(card);
+                }
+
+                bool CanActivateCondition(Hashtable hashtable) => CardEffectCommons.IsExistOnBattleArea(card);
+
+                IEnumerator ActivateCoroutine(Hashtable hashtable)
+                {
+                    card.Owner.UntilCalculateFixedCostEffect.Add((timing) => CardEffectFactory.GrantedReduceLinkCostClass(
+                        card: card, 
+                        reducedCost: 1,
+                        cardSourceCondition: CardCondition,
+                        permanentCondition: PermanentCondition,
+                        rootCondition: RootCondition
+                    ));
+
+                    yield return null;
+                }
+            }
+            #endregion
+
+            #region Reduce Link cost - Not Shown
+            if (timing == EffectTiming.None)
+            {
+                cardEffects.Add(CardEffectFactory.ReduceLinkCostClass(
+                    card: card, 
+                    canUseCondition: CanUseCondition,
+                    isInheritedEffect: true,
+                    isOptional: true,
+                    reducedCost: 1,
+                    cardSourceCondition: CardCondition,
+                    permanentCondition: PermanentCondition,
+                    rootCondition: RootCondition
+                ));
+
+                bool CanUseCondition(Hashtable hashtable)
+                {
+                    return CardEffectCommons.IsExistOnBattleArea(card)
+                        && CardEffectCommons.IsOwnerTurn(card);
+                }
+            }
+            #endregion
+
+            return cardEffects;
+        }
+    }
+}

+ 27 - 6
Assets/Scripts/CardEffect/P/Black/P_234.cs

@@ -99,20 +99,39 @@ namespace DCGO.CardEffects.P
                             || cardSource.EqualsTraits("Navi")
                             || cardSource.EqualsTraits("Tool")
                             || cardSource.EqualsTraits("Leviathan"))
-                        && cardSource.CanLink(false)
-                        && card.Owner.MaxMemoryCost >= cardSource.linkCondition.cost - 2;
+                        && cardSource.CanLink(true);
                 }
 
                 bool CanSelectPermanentCondition(Permanent permanent, CardSource cardSource)
                 {
                     return CardEffectCommons.IsPermanentExistsOnOwnerBattleAreaDigimon(permanent, card)
-                        && cardSource.CanLinkToTargetPermanent(permanent, false);
+                        && cardSource.CanLinkToTargetPermanent(permanent, true);
                 }
 
                 IEnumerator ActivateCoroutine(Hashtable hashtable)
                 {
                     yield return ContinuousController.instance.StartCoroutine(new SuspendPermanentsClass(new List<Permanent>() { card.PermanentOfThisCard() }, CardEffectCommons.CardEffectHashtable(activateClass)).Tap());
                     
+                    #region Link Cost Reduction
+                    ICardEffect GetCardEffect(EffectTiming _timing)
+                    {
+                        if (_timing == EffectTiming.None)
+                        {
+                            return CardEffectFactory.GrantedReduceLinkCostClass(
+                                card: card, 
+                                reducedCost: 2,
+                                cardSourceCondition: _ => true,
+                                permanentCondition: _ => true,
+                                rootCondition: _ => true
+                            );
+                        }
+
+                        return null;
+                    }
+
+                    card.Owner.UntilCalculateFixedCostEffect.Add(GetCardEffect);
+                    #endregion
+
                     if (CardEffectCommons.HasMatchConditionOwnersHand(card, CanSelectCardCondition))
                     {
                         SelectHandEffect selectHandEffect = GManager.instance.GetComponent<SelectHandEffect>();
@@ -160,13 +179,15 @@ namespace DCGO.CardEffects.P
 
                                 IEnumerator SelectPermanentCoroutine(Permanent permanent)
                                 {
-                                    yield return ContinuousController.instance.StartCoroutine(card.Owner.AddMemory(-Math.Max(0,cardSource.linkCondition.cost - 2), activateClass));
-
-                                     yield return ContinuousController.instance.StartCoroutine(permanent.AddLinkCard(cardSource, activateClass));
+                                    yield return ContinuousController.instance.StartCoroutine(new ILinkCard(true, cardSource, permanent, activateClass).LinkCard());
                                 }
                             }
                         }
                     }
+
+                    #region Remove Link Cost Reduction
+                    card.Owner.UntilCalculateFixedCostEffect.Remove(GetCardEffect);
+                    #endregion
                 }
             }
             #endregion

+ 27 - 4
Assets/Scripts/CardEffect/ST22/Red/ST22_12.cs

@@ -84,7 +84,7 @@ namespace DCGO.CardEffects.ST22
                 bool CanSelectCardConditionShared(CardSource source)
                 {
                     return source.IsDigimon &&
-                           source.CanLinkToTargetPermanent(card.PermanentOfThisCard(), false) &&
+                           source.CanLinkToTargetPermanent(card.PermanentOfThisCard(), true) &&
                            (source.ContainsTraits("Social") || source.ContainsTraits("Navi") || source.ContainsTraits("Tool"));
                 }
 
@@ -104,6 +104,27 @@ namespace DCGO.CardEffects.ST22
                 {
                     bool canSelectHand = CardEffectCommons.HasMatchConditionOwnersHand(card, CanSelectCardConditionShared);
                     bool canSelectSources = card.PermanentOfThisCard().DigivolutionCards.Filter(x => CanSelectCardConditionShared(x)).Count > 0;
+
+                    #region Link Cost Reduction
+                    ICardEffect GetCardEffect(EffectTiming _timing)
+                    {
+                        if (_timing == EffectTiming.None)
+                        {
+                            return CardEffectFactory.GrantedReduceLinkCostClass(
+                                card: card, 
+                                reducedCost: 2,
+                                cardSourceCondition: _ => true,
+                                permanentCondition: _ => true,
+                                rootCondition: _ => true
+                            );
+                        }
+
+                        return null;
+                    }
+
+                    card.Owner.UntilCalculateFixedCostEffect.Add(GetCardEffect);
+                    #endregion
+
                     if (canSelectHand || canSelectSources)
                     {
                         if (canSelectHand && canSelectSources)
@@ -189,11 +210,13 @@ namespace DCGO.CardEffects.ST22
 
                         if (selectedCard != null)
                         {
-                            yield return ContinuousController.instance.StartCoroutine(card.Owner.AddMemory(-Mathf.Max(0,selectedCard.linkCondition.cost - 2), activateClass));
-
-                            yield return ContinuousController.instance.StartCoroutine(card.PermanentOfThisCard().AddLinkCard(selectedCard, activateClass));
+                            yield return ContinuousController.instance.StartCoroutine(new ILinkCard(true, selectedCard, card.PermanentOfThisCard(), activateClass).LinkCard());
                         }
                     }
+
+                    #region Remove Link Cost Reduction
+                    card.Owner.UntilCalculateFixedCostEffect.Remove(GetCardEffect);
+                    #endregion
                 }
             }
 

+ 50 - 0
Assets/Scripts/Script/CardController.cs

@@ -3311,6 +3311,56 @@ public class IPlacePermanentToLinkCards
 
 #endregion
 
+#region Link a Card to a Permanent
+public class ILinkCard
+{
+    public ILinkCard(bool payCost, CardSource card, Permanent permanent, ICardEffect cardEffect)
+    {
+        _payCost = payCost;
+        _linkCard = _linkCard;
+        _permanent = permanent;
+        _cardEffect = cardEffect;
+    }
+
+    bool _payCost = false;
+    CardSource _linkCard = null;
+    Permanent _permanent = null;
+    ICardEffect _cardEffect = null;
+    public bool WasLinked = false;
+
+    public IEnumerator LinkCard()
+    {
+        if (_linkCard == null) yield break;
+        if (_permanent == null || _permanent.TopCard == null) yield break;
+        if (_cardEffect == null) yield break;
+
+        #region Trigger When Would Link effects
+        SelectCardEffect.Root root = CardEffectCommons.IsExistOnHand(_linkCard) ? SelectCardEffect.Root.Hand : SelectCardEffect.Root.None;
+
+        yield return ContinuousController.instance.StartCoroutine(GManager.instance.autoProcessing_CutIn.StackSkillInfos(
+            CardEffectCommons.WouldLinkHashtable(_linkCard, _permanent, root, null),
+            EffectTiming.WhenWouldLink));
+
+        yield return ContinuousController.instance.StartCoroutine(GManager.instance.autoProcessing_CutIn.TriggeredSkillProcess(false, null));
+        #endregion
+
+        if (_payCost)
+        {
+            int Cost = _linkCard.GetChangedLinkCost(_permanent, root);
+
+            yield return ContinuousController.instance.StartCoroutine(_linkCard.Owner.AddMemory(-1 * Cost, _cardEffect));
+        }
+
+        if(root == SelectCardEffect.Root.Hand)
+            yield return ContinuousController.instance.StartCoroutine(_permanent.AddLinkCard(_linkCard, _cardEffect));
+        else
+            yield return ContinuousController.instance.StartCoroutine(new IPlacePermanentToLinkCards(new List<Permanent[]>() { new Permanent[] { _linkCard.PermanentOfThisCard(), _permanent } }, _cardEffect).PlacePermanentToLinkCards());
+
+        WasLinked = _permanent.LinkedCards.Contains(_linkCard);
+    }
+}
+#endregion
+
 #region Place permanents to security
 
 public class IPutSecurityPermanent

+ 41 - 0
Assets/Scripts/Script/CardEffectCommons/CanUseEffects/WhenWouldLink.cs

@@ -0,0 +1,41 @@
+using System.Collections;
+using System.Collections.Generic;
+using System;
+using System.Linq;
+using UnityEngine;
+
+public partial class CardEffectCommons
+{
+    #region Can trigger "When permanent would be played" effects of 1 permanent
+
+    public static bool CanTriggerWhenWouldLink(Hashtable hashtable, Func<CardSource, bool> cardCondition, Func<Permanent, bool> permanentCondition, Func<SelectCardEffect.Root, bool> rootCondition = null, Func<ICardEffect, bool> cardEffectCondition = null)
+    {
+        CardSource cardSource = GetCardFromHashtable(hashtable);
+
+        if (cardSource != null)
+        {
+            if (cardCondition == null || cardCondition(cardSource))
+            {
+                Permanent permanent = GetPermanentFromHashtable(hashtable);
+
+                if (permanentCondition == null || permanentCondition(permanent))
+                {
+                    SelectCardEffect.Root root = GetRootFromHashtable(hashtable);
+
+                    if (rootCondition == null || rootCondition(root))
+                    {
+                        ICardEffect cardEffect = GetCardEffectFromHashtable(hashtable);
+
+                        if (cardEffectCondition == null || cardEffectCondition(cardEffect))
+                        {
+                            return true;
+                        }
+                    }
+                }
+            }
+        }
+
+        return false;
+    }
+    #endregion
+}

+ 15 - 0
Assets/Scripts/Script/CardEffectCommons/HashtableSetting.cs

@@ -192,6 +192,21 @@ public partial class CardEffectCommons
     }
     #endregion
 
+    #region Hashtable when a card would be linked
+    public static Hashtable WouldLinkHashtable(CardSource card, Permanent targetPermanent, SelectCardEffect.Root root, ICardEffect cardEffect)
+    {
+        Hashtable hashtable = new Hashtable()
+        {
+            {"Card", card},
+            {"Root", root},
+            {"CardEffect", cardEffect},
+            {"Permanent", targetPermanent},
+        };
+
+        return hashtable;
+    }
+    #endregion
+
     #region Hashtable used when check whether the card can trigger [On Play] effect
     public static Hashtable OnPlayCheckHashtableOfCard(CardSource cardSource)
     {

+ 50 - 6
Assets/Scripts/Script/CardEffectFactory/KeyWordEffects/Link.cs

@@ -96,16 +96,60 @@ public partial class CardEffectFactory
 
             if (selectedPermanent != null)
             {
-                yield return ContinuousController.instance.StartCoroutine(card.Owner.AddMemory(-card.linkCondition.cost, activateClass));
-
-                if(CardEffectCommons.IsExistOnHand(card))
-                    yield return ContinuousController.instance.StartCoroutine(selectedPermanent.AddLinkCard(card, activateClass));
-                else
-                    yield return ContinuousController.instance.StartCoroutine(new IPlacePermanentToLinkCards(new List<Permanent[]>() { new Permanent[] { card.PermanentOfThisCard(), selectedPermanent } }, activateClass).PlacePermanentToLinkCards());
+                yield return ContinuousController.instance.StartCoroutine(new ILinkCard(true, card, selectedPermanent, activateClass).LinkCard());
             }
         }
 
         return activateClass;
     }
     #endregion
+
+    #region Granted Link Cost Reduction
+    public static ChangeLinkCostClass GrantedReduceLinkCostClass(CardSource card, int reducedCost, Func<CardSource, bool> cardSourceCondition, Func<Permanent, bool> permanentCondition, Func<SelectCardEffect.Root, bool> rootCondition)
+    {
+        return ReduceLinkCostClass(card, _ => true, false, false, reducedCost, cardSourceCondition, permanentCondition, rootCondition);
+    }
+    #endregion
+
+    #region Get when would link granted cost reduction
+    public static ChangeLinkCostClass GrantedChangeLinkCostClass(CardSource card, string effectName, Func<CardSource, Permanent, int, SelectCardEffect.Root, int> changeCostFunc, Func<CardSource, bool> cardSourceCondition, Func<Permanent, bool> permanentCondition, Func<SelectCardEffect.Root, bool> rootCondition, Func<bool> isUpDown)
+    {
+        return ChangeLinkCostClass(card, _ => true, effectName, false, false, changeCostFunc, cardSourceCondition, permanentCondition, rootCondition, isUpDown);
+    }
+    #endregion
+
+    #region GetChangeLinkCostClass
+    public static ChangeLinkCostClass ChangeLinkCostClass(CardSource card, Func<Hashtable, bool> canUseCondition, string effectName, bool isInheritedEffect, bool isOptional, Func<CardSource, Permanent, int, SelectCardEffect.Root, int> changeCostFunc, Func<CardSource, bool> cardSourceCondition, Func<Permanent, bool> permanentCondition, Func<SelectCardEffect.Root, bool> rootCondition, Func<bool> isUpDown)
+    {
+        ChangeLinkCostClass changeLinkCostClass = new ();
+        changeLinkCostClass.SetUpICardEffect(effectName, canUseCondition, card);
+        changeLinkCostClass.SetUpChangeLinkCostClass(changeCostFunc, cardSourceCondition, permanentCondition, rootCondition, isUpDown);
+        changeLinkCostClass.SetNotShowUI(isOptional);
+        changeLinkCostClass.SetIsInheritedEffect(isInheritedEffect);
+        return changeLinkCostClass;
+    }
+    #endregion
+
+    #region GetChangeLinkCostClass for Cost Reduction
+    public static ChangeLinkCostClass ReduceLinkCostClass(CardSource card, Func<Hashtable, bool> canUseCondition, bool isInheritedEffect, bool isOptional, int reducedCost, Func<CardSource, bool> cardSourceCondition, Func<Permanent, bool> permanentCondition, Func<SelectCardEffect.Root, bool> rootCondition)
+    {
+        return ChangeLinkCostClass(card, canUseCondition, $"Link Cost -{reducedCost}", isInheritedEffect, isOptional, ChangeCost, cardSourceCondition, permanentCondition, rootCondition, () => true);
+
+        int ChangeCost(CardSource cardSource, Permanent targetPermanent, int Cost, SelectCardEffect.Root root)
+        {
+            if (cardSourceCondition(cardSource))
+            {
+                if (rootCondition(root))
+                {
+                    if (permanentCondition(targetPermanent))
+                    {
+                        Cost -= reducedCost;
+                    }
+                }
+            }
+
+            return Cost;
+        }
+    }
+    #endregion
 }

+ 10 - 0
Assets/Scripts/Script/CardEffectInterfaces.cs

@@ -265,6 +265,16 @@ public interface IChangeCostEffect
 }
 #endregion
 
+#region "Change target card's cost" effect
+public interface IChangeLinkCostEffect
+{
+    int GetCost(int cost, CardSource cardSource, Permanent permanent, SelectCardEffect.Root root);
+    bool CardCondition(CardSource cardSource);
+    bool PermanentCondition(Permanent permanent);
+    bool IsUpDown();
+}
+#endregion
+
 #region "Change the maximum DP of DP-based deletion effect" effect
 public interface IChangeDPDeleteEffectMaxDPEffect
 {

+ 58 - 0
Assets/Scripts/Script/CardEffects/ChangeLinkCostClass.cs

@@ -0,0 +1,58 @@
+using System.Collections.Generic;
+using System;
+public class ChangeLinkCostClass : ICardEffect, IChangeLinkCostEffect
+{
+    Func<CardSource, Permanent, int, SelectCardEffect.Root, int> _changeCostFunc { get; set; }
+    Func<CardSource, bool> _cardSourceCondition { get; set; }
+    Func<Permanent, bool> _permanentCondition { get; set; }
+    Func<SelectCardEffect.Root, bool> _rootCondition { get; set; }
+    Func<bool> _isUpDown { get; set; }
+    public void SetUpChangeLinkCostClass(Func<CardSource, Permanent, int, SelectCardEffect.Root, int> changeCostFunc, Func<CardSource, bool> cardSourceCondition, Func<Permanent, bool> permanentCondition, Func<SelectCardEffect.Root, bool> rootCondition, Func<bool> isUpDown)
+    {
+        _changeCostFunc = changeCostFunc;
+        _cardSourceCondition = cardSourceCondition;
+        _permanentCondition = permanentCondition;
+        _rootCondition = rootCondition;
+        _isUpDown = isUpDown;
+    }
+    public int GetCost(int cost, CardSource cardSource, Permanent permanent, SelectCardEffect.Root root)
+    {
+        if (cardSource != null
+            && CardCondition(cardSource)
+            && PermanentCondition(permanent)
+            && _changeCostFunc != null
+            && _rootCondition != null
+            && _rootCondition(root))
+        {
+            int newCost = _changeCostFunc(cardSource, permanent, cost, root);
+
+            if (IsUpDown()
+                && newCost < cost)
+            {
+                newCost = cost;
+            }
+
+            cost = newCost;
+        }
+
+        return cost;
+    }
+
+    public bool CardCondition(CardSource cardSource)
+    {
+        return _cardSourceCondition != null
+            && _cardSourceCondition(cardSource);
+    }
+
+    public bool PermanentCondition(Permanent permanent)
+    {
+        return _permanentCondition != null
+            && _permanentCondition(permanent);
+    }
+
+    public bool IsUpDown()
+    {
+        return _isUpDown != null
+            && _isUpDown();
+    }
+}

+ 100 - 13
Assets/Scripts/Script/CardSource.cs

@@ -2937,15 +2937,8 @@ public class CardSource : MonoBehaviour
     {
         if (linkCondition != null)
         {
-            if (PayCost)
-            {
-                int cost = linkCondition.cost;
+            SelectCardEffect.Root root = CardEffectCommons.IsExistOnHand(this) ? SelectCardEffect.Root.Hand : SelectCardEffect.Root.None;
 
-                if (Owner.MaxMemoryCost < cost)
-                {
-                    return false;
-                }
-            }
             if (allowBreeding)
             {
                 if (Owner.GetFieldPermanents().Count >= 1)
@@ -2956,7 +2949,19 @@ public class CardSource : MonoBehaviour
                         {
                             if (linkCondition.digimonCondition(digimon))
                             {
-                                return true;
+                                if (PayCost)
+                                {
+                                    int cost = GetChangedLinkCost(digimon, root);
+
+                                    if (Owner.MaxMemoryCost >= cost)
+                                    {
+                                        return true;
+                                    }
+                                }
+                                else
+                                {
+                                    return true;
+                                }
                             }
                         }
                     }
@@ -2972,7 +2977,19 @@ public class CardSource : MonoBehaviour
                         {
                             if (linkCondition.digimonCondition(digimon))
                             {
-                                return true;
+                                if (PayCost)
+                                {
+                                    int cost = GetChangedLinkCost(digimon, root);
+
+                                    if (Owner.MaxMemoryCost >= cost)
+                                    {
+                                        return true;
+                                    }
+                                }
+                                else
+                                {
+                                    return true;
+                                }
                             }
                         }
                     }
@@ -3041,6 +3058,76 @@ public class CardSource : MonoBehaviour
 
     #endregion
 
+    #region Get Link Cost Accounting for Cost Reduction
+
+    public int GetChangedLinkCost(Permanent targetPermanent, SelectCardEffect.Root root)
+    {
+        if (linkCondition == null) return 0;
+
+        int Cost = linkCondition.cost;
+
+        List<ICardEffect> changeLinkCostCardEffects = new List<ICardEffect>();
+
+        #region the effects of permanents
+
+        changeLinkCostCardEffects = changeLinkCostCardEffects
+            .Concat(
+            GManager.instance.turnStateMachine.gameContext.Players_ForTurnPlayer
+                .Map(player => player.GetFieldPermanents())
+                .Flat()
+                .Filter(permanent => permanent != PermanentOfThisCard())
+                .Map(permanent => permanent.EffectList(EffectTiming.None))
+                .Flat()
+                .Filter(cardEffect => cardEffect is IChangeLinkCostEffect && cardEffect.CanUse(null)
+                    && ((IChangeLinkCostEffect)cardEffect).CardCondition(this)
+                    && ((IChangeLinkCostEffect)cardEffect).PermanentCondition(targetPermanent)))
+                .ToList();
+
+        #endregion
+
+        #region the effects of players
+
+        changeLinkCostCardEffects = changeLinkCostCardEffects
+            .Concat(
+            GManager.instance.turnStateMachine.gameContext.Players_ForTurnPlayer
+                .Map(player => player.EffectList(EffectTiming.None))
+                .Flat()
+                .Filter(cardEffect => cardEffect is IChangeLinkCostEffect && cardEffect.CanUse(null)
+                    && ((IChangeLinkCostEffect)cardEffect).CardCondition(this)
+                    && ((IChangeLinkCostEffect)cardEffect).PermanentCondition(targetPermanent)))
+                .ToList();
+
+        #endregion
+
+        #region the effects of itself
+
+        changeLinkCostCardEffects = changeLinkCostCardEffects
+        .Concat(
+        EffectList(EffectTiming.None)
+        .Filter(cardEffect => cardEffect is IChangeLinkCostEffect && cardEffect.CanUse(null)
+                && ((IChangeLinkCostEffect)cardEffect).CardCondition(this)
+                    && ((IChangeLinkCostEffect)cardEffect).PermanentCondition(targetPermanent)))
+        .ToList();
+
+        #endregion
+
+        List<ICardEffect> changeLinkCostCardEffects_NotIsUpDown = changeLinkCostCardEffects
+            .Filter(cardEffect => !((IChangeLinkCostEffect)cardEffect).IsUpDown());
+
+        List<ICardEffect> changeLinkCostCardEffects_IsUpDown = changeLinkCostCardEffects
+            .Filter(cardEffect => ((IChangeLinkCostEffect)cardEffect).IsUpDown());
+
+        changeLinkCostCardEffects_NotIsUpDown
+            .ForEach(cardEffect => Cost = ((IChangeLinkCostEffect)cardEffect).GetCost(Cost, this, targetPermanent, root));
+
+        changeLinkCostCardEffects_IsUpDown
+            .ForEach(cardEffect => Cost = ((IChangeLinkCostEffect)cardEffect).GetCost(Cost, this, targetPermanent, root));
+
+        return Math.Max(0, Cost);
+    }
+
+    #endregion
+
     #region whether target permanent can Link into this card
 
     public bool CanLinkToTargetPermanent(Permanent targetPermanent, bool PayCost, bool allowBreeding = false)
@@ -3051,7 +3138,7 @@ public class CardSource : MonoBehaviour
             {
                 if(allowBreeding || !targetPermanent.TopCard.Owner.GetBreedingAreaPermanents().Contains(targetPermanent))
                 {
-                    if (this.CanLink(PayCost, allowBreeding))
+                    if (this.CanLink(false, allowBreeding)) // Don't check PayCost in CanLink since this method will check again anyway
                     {
                         if (linkCondition != null)
                         {
@@ -3059,9 +3146,9 @@ public class CardSource : MonoBehaviour
                             {
                                 if (PayCost)
                                 {
-                                    int cost = linkCondition.cost;
+                                    SelectCardEffect.Root root = CardEffectCommons.IsExistOnHand(this) ? SelectCardEffect.Root.Hand : SelectCardEffect.Root.None;
 
-                                    cost = GetChangedCostItselef(cost, SelectCardEffect.Root.Hand, new List<Permanent>() { targetPermanent }, checkAvailability: true);
+                                    int cost = GetChangedLinkCost(targetPermanent, root);
 
                                     if (Owner.MaxMemoryCost < cost)
                                     {

+ 1 - 0
Assets/Scripts/Script/ICardEffect.cs

@@ -988,6 +988,7 @@ public enum EffectTiming
     OnReturnCardsToHandFromTrash,
     AfterEffectsActivate,
     WhenWouldDigivolutionCardDiscarded,
+    WhenWouldLink,
     WhenLinked,
     WhenTopCardTrashed,
     RulesTiming,