Merge branch 'hasManaAbility' into 'master'

fix hasManaAbility

Closes #2130

See merge request core-developers/forge!6465
This commit is contained in:
Michael Kamensky
2022-04-01 03:04:38 +00:00
8 changed files with 14 additions and 21 deletions

View File

@@ -142,7 +142,7 @@ public class ControlGainAi extends SpellAbilityAi {
return true; return true;
} }
if (c.canBeControlledBy(ai)) { if (!c.canBeControlledBy(ai)) {
return false; return false;
} }

View File

@@ -115,7 +115,8 @@ public class ForgeScript {
return true; return true;
} }
for (final Trigger trig : cardState.getTriggers()) { for (final Trigger trig : cardState.getTriggers()) {
if (trig.getOverridingAbility() != null && trig.getOverridingAbility().isManaAbility()) { SpellAbility sa = trig.getOverridingAbility();
if (sa != null && sa.isManaAbility()) {
return true; return true;
} }
} }

View File

@@ -6,6 +6,7 @@ import java.util.Set;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.card.CardState; import forge.game.card.CardState;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
import forge.game.trigger.Trigger;
import forge.game.zone.Zone; import forge.game.zone.Zone;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
@@ -63,6 +64,9 @@ public abstract class TriggerReplacementBase extends CardTraitBase implements II
* @return the overridingAbility * @return the overridingAbility
*/ */
public SpellAbility getOverridingAbility() { public SpellAbility getOverridingAbility() {
if (overridingAbility != null && !overridingAbility.isTrigger() && this instanceof Trigger) {
overridingAbility.setTrigger((Trigger) this);
}
return this.overridingAbility; return this.overridingAbility;
} }

View File

@@ -21,9 +21,7 @@ import forge.game.mana.Mana;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.spellability.OptionalCost; import forge.game.spellability.OptionalCost;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
import forge.game.spellability.SpellAbilityPredicates;
import forge.game.spellability.SpellAbilityStackInstance; import forge.game.spellability.SpellAbilityStackInstance;
import forge.game.trigger.Trigger;
import forge.game.zone.Zone; import forge.game.zone.Zone;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
import forge.item.PaperCard; import forge.item.PaperCard;
@@ -388,15 +386,6 @@ public class CardProperty {
if (!card.equals(source.getEffectSource())) { if (!card.equals(source.getEffectSource())) {
return false; return false;
} }
} else if (property.equals("withoutManaAbility")) {
if (Iterables.any(card.getSpellAbilities(), SpellAbilityPredicates.isManaAbility())) {
return false;
}
for (final Trigger trig : card.getTriggers()) {
if (trig.getOverridingAbility() != null && !trig.getOverridingAbility().isManaAbility()) {
return false;
}
}
} else if (property.equals("CanBeSacrificedBy") && spellAbility instanceof SpellAbility) { } else if (property.equals("CanBeSacrificedBy") && spellAbility instanceof SpellAbility) {
// used for Emerge and Offering, these are SpellCost, not effect // used for Emerge and Offering, these are SpellCost, not effect
if (!card.canBeSacrificedBy((SpellAbility) spellAbility, false)) { if (!card.canBeSacrificedBy((SpellAbility) spellAbility, false)) {

View File

@@ -3,11 +3,10 @@ ManaCost:B
Types:Creature Human Cleric Types:Creature Human Cleric
PT:1/1 PT:1/1
K:Lifelink K:Lifelink
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigExile | CheckSVar$ GraveCheck | TriggerDescription$ When CARDNAME enters the battlefield, if it entered from your graveyard or you cast it from your graveyard, exile it. If you do, create a 5/5 black Demon creature token with flying. T:Mode$ ChangesZone | Origin$ Graveyard | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigExile | TriggerDescription$ When CARDNAME enters the battlefield, if it entered from your graveyard or you cast it from your graveyard, exile it. If you do, create a 5/5 black Demon creature token with flying.
T:Mode$ ChangesZone | Destination$ Battlefield | ValidCard$ Card.Self+wasCastFromYourGraveyardByYou | Execute$ TrigExile | Secondary$ True | TriggerDescription$ When CARDNAME enters the battlefield, if it entered from your graveyard or you cast it from your graveyard, exile it. If you do, create a 5/5 black Demon creature token with flying.
SVar:TrigExile:DB$ ChangeZone | Origin$ Battlefield | Destination$ Exile | Defined$ Self | SubAbility$ DBToken | RememberChanged$ True SVar:TrigExile:DB$ ChangeZone | Origin$ Battlefield | Destination$ Exile | Defined$ Self | SubAbility$ DBToken | RememberChanged$ True
SVar:DBToken:DB$ Token | TokenAmount$ 1 | TokenScript$ b_5_5_demon_flying | TokenOwner$ You | ConditionDefined$ Remembered | ConditionPresent$ Card.Self | ConditionCompare$ GE1 SVar:DBToken:DB$ Token | TokenAmount$ 1 | TokenScript$ b_5_5_demon_flying | TokenOwner$ You | ConditionDefined$ Remembered | ConditionPresent$ Card.Self | ConditionCompare$ GE1
SVar:GraveCheck:Count$wasCastFromYourGraveyardByYou.1.0/Plus.GraveCheck2
SVar:GraveCheck2:TriggeredCardLKI$Valid Card.inZoneGraveyard
DeckHas:Ability$Token DeckHas:Ability$Token
DeckHints:Ability$Graveyard DeckHints:Ability$Graveyard
Oracle:Lifelink (Damage dealt by this creature also causes you to gain that much life.)\nWhen Archfiend's Vessel enters the battlefield, if it entered from your graveyard or you cast it from your graveyard, exile it. If you do, create a 5/5 black Demon creature token with flying. Oracle:Lifelink (Damage dealt by this creature also causes you to gain that much life.)\nWhen Archfiend's Vessel enters the battlefield, if it entered from your graveyard or you cast it from your graveyard, exile it. If you do, create a 5/5 black Demon creature token with flying.

View File

@@ -4,8 +4,8 @@ Types:Creature Spirit Knight
PT:2/2 PT:2/2
K:Flying K:Flying
K:Lifelink K:Lifelink
T:Mode$ ChangesZone | Origin$ Graveyard | Destination$ Battlefield | TriggerZones$ Battlefield | ValidCard$ Creature.YouOwn+Other,Creature.Self | Execute$ TrigPutCounter | TriggerDescription$ Whenever CARDNAME or another creature enters the battlefield under your control, if that creature entered from a graveyard or you cast it from a graveyard, put a +1/+1 counter on CARDNAME. T:Mode$ ChangesZone | Origin$ Graveyard | Destination$ Battlefield | TriggerZones$ Battlefield | ValidCard$ Creature.YouCtrl+Other,Creature.Self | Execute$ TrigPutCounter | TriggerDescription$ Whenever CARDNAME or another creature enters the battlefield under your control, if that creature entered from a graveyard or you cast it from a graveyard, put a +1/+1 counter on CARDNAME.
T:Mode$ ChangesZone | Destination$ Battlefield | TriggerZones$ Battlefield | ValidCard$ Creature.YouOwn+Other+wasCastFromGraveyard,Creature.Self+wasCastFromGraveyard | Execute$ TrigPutCounter | Secondary$ True | TriggerDescription$ Whenever CARDNAME or another creature enters the battlefield under your control, if that creature entered from a graveyard or you cast it from a graveyard, put a +1/+1 counter on CARDNAME. T:Mode$ ChangesZone | Destination$ Battlefield | TriggerZones$ Battlefield | ValidCard$ Creature.YouCtrl+Other+wasCastFromGraveyardByYou,Creature.Self+wasCastFromGraveyardByYou | Execute$ TrigPutCounter | Secondary$ True | TriggerDescription$ Whenever CARDNAME or another creature enters the battlefield under your control, if that creature entered from a graveyard or you cast it from a graveyard, put a +1/+1 counter on CARDNAME.
SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterNum$ 1 | CounterType$ P1P1 SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterNum$ 1 | CounterType$ P1P1
DeckHas:Ability$Counters DeckHas:Ability$Counters
Oracle:Flying, lifelink\nWhenever Breathless Knight or another creature enters the battlefield under your control, if that creature entered from a graveyard or you cast it from a graveyard, put a +1/+1 counter on Breathless Knight. Oracle:Flying, lifelink\nWhenever Breathless Knight or another creature enters the battlefield under your control, if that creature entered from a graveyard or you cast it from a graveyard, put a +1/+1 counter on Breathless Knight.

View File

@@ -3,7 +3,7 @@ ManaCost:3 R
Types:Creature Vampire Types:Creature Vampire
PT:3/2 PT:3/2
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDestroy | TriggerDescription$ When CARDNAME enters the battlefield, destroy up to X target artifacts without mana abilities, where X is the number of Vampires you control. T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDestroy | TriggerDescription$ When CARDNAME enters the battlefield, destroy up to X target artifacts without mana abilities, where X is the number of Vampires you control.
SVar:TrigDestroy:DB$ Destroy | TargetMin$ 0 | TargetMax$ X | ValidTgts$ Artifact.withoutManaAbility | TgtPrompt$ Select up to X target artifacts without mana abilities SVar:TrigDestroy:DB$ Destroy | TargetMin$ 0 | TargetMax$ X | ValidTgts$ Artifact.!hasManaAbility | TgtPrompt$ Select up to X target artifacts without mana abilities
SVar:X:Count$Valid Vampire.YouCtrl SVar:X:Count$Valid Vampire.YouCtrl
DeckHints:Type$Vampire DeckHints:Type$Vampire
AI:RemoveDeck:Random AI:RemoveDeck:Random

View File

@@ -487,7 +487,7 @@ public final class CardScriptParser {
"HasDevoured", "HasNotDevoured", "IsMonstrous", "IsNotMonstrous", "HasDevoured", "HasNotDevoured", "IsMonstrous", "IsNotMonstrous",
"CostsPhyrexianMana", "IsRemembered", "IsNotRemembered", "CostsPhyrexianMana", "IsRemembered", "IsNotRemembered",
"IsImprinted", "IsNotImprinted", "hasActivatedAbilityWithTapCost", "IsImprinted", "IsNotImprinted", "hasActivatedAbilityWithTapCost",
"hasActivatedAbility", "hasManaAbility", "withoutManaAbility", "hasActivatedAbility", "hasManaAbility",
"hasNonManaActivatedAbility", "NoAbilities", "HasCounters", "hasNonManaActivatedAbility", "NoAbilities", "HasCounters",
"wasNotCast", "ChosenType", "IsNotChosenType", "IsCommander", "wasNotCast", "ChosenType", "IsNotChosenType", "IsCommander",
"IsNotCommander","IsRenowned", "IsNotRenowned"); "IsNotCommander","IsRenowned", "IsNotRenowned");