mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 10:48:00 +00:00
Merge branch 'master' into 'm19'
This commit is contained in:
@@ -76,6 +76,51 @@ public final class CardFacePredicates {
|
||||
};
|
||||
}
|
||||
|
||||
static class ValidPredicate implements Predicate<ICardFace> {
|
||||
private String valid;
|
||||
|
||||
public ValidPredicate(final String valid) {
|
||||
this.valid = valid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(ICardFace input) {
|
||||
String k[] = valid.split("\\.", 2);
|
||||
|
||||
if ("Card".equals(k[0])) {
|
||||
// okay
|
||||
} else if ("Permanent".equals(k[0])) {
|
||||
if (input.getType().isInstant() || input.getType().isSorcery()) {
|
||||
return false;
|
||||
}
|
||||
} else if (!input.getType().hasStringType(k[0])) {
|
||||
return false;
|
||||
}
|
||||
if (k.length > 1) {
|
||||
for (final String m : k[1].split("\\+")) {
|
||||
if (!hasProperty(input, m)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static protected boolean hasProperty(ICardFace input, final String v) {
|
||||
if (v.startsWith("non")) {
|
||||
return !hasProperty(input, v.substring(3));
|
||||
} else if (!input.getType().hasStringType(v)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static Predicate<ICardFace> valid(final String val) {
|
||||
return new ValidPredicate(val);
|
||||
}
|
||||
|
||||
public static class Presets {
|
||||
/** The Constant isBasicLand. */
|
||||
public static final Predicate<ICardFace> IS_BASIC_LAND = new Predicate<ICardFace>() {
|
||||
|
||||
@@ -368,6 +368,7 @@ public class GameAction {
|
||||
|
||||
final Map<String, Object> runParams = Maps.newHashMap();
|
||||
runParams.put("Card", lastKnownInfo);
|
||||
runParams.put("Cause", cause);
|
||||
runParams.put("Origin", zoneFrom != null ? zoneFrom.getZoneType().name() : null);
|
||||
runParams.put("Destination", zoneTo.getZoneType().name());
|
||||
runParams.put("SpellAbilityStackInstance", game.stack.peek());
|
||||
|
||||
@@ -105,17 +105,8 @@ public class ChooseCardNameEffect extends SpellAbilityEffect {
|
||||
final String message = validDesc.equals("card") ? "Name a card" : "Name a " + validDesc + " card.";
|
||||
|
||||
Predicate<ICardFace> cpp = Predicates.alwaysTrue();
|
||||
if ( StringUtils.containsIgnoreCase(valid, "nonland") ) {
|
||||
cpp = CardFacePredicates.Presets.IS_NON_LAND;
|
||||
}
|
||||
if ( StringUtils.containsIgnoreCase(valid, "nonbasic") ) {
|
||||
cpp = Predicates.not(CardFacePredicates.Presets.IS_BASIC_LAND);
|
||||
}
|
||||
|
||||
if ( StringUtils.containsIgnoreCase(valid, "noncreature") ) {
|
||||
cpp = Predicates.not(CardFacePredicates.Presets.IS_CREATURE);
|
||||
} else if ( StringUtils.containsIgnoreCase(valid, "creature") ) {
|
||||
cpp = CardFacePredicates.Presets.IS_CREATURE;
|
||||
if (sa.hasParam("ValidCards")) {
|
||||
cpp = CardFacePredicates.valid(valid);
|
||||
}
|
||||
|
||||
chosen = p.getController().chooseCardName(sa, cpp, valid, message);
|
||||
|
||||
@@ -65,57 +65,68 @@ public class TriggerChangesZone extends Trigger {
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public final boolean performTest(final java.util.Map<String, Object> runParams2) {
|
||||
if (this.mapParams.containsKey("Origin")) {
|
||||
if (!this.mapParams.get("Origin").equals("Any")) {
|
||||
if (this.mapParams.get("Origin") == null) {
|
||||
public final boolean performTest(final Map<String, Object> runParams2) {
|
||||
if (hasParam("Origin")) {
|
||||
if (!getParam("Origin").equals("Any")) {
|
||||
if (getParam("Origin") == null) {
|
||||
return false;
|
||||
}
|
||||
if (!ArrayUtils.contains(
|
||||
this.mapParams.get("Origin").split(","), runParams2.get("Origin")
|
||||
getParam("Origin").split(","), runParams2.get("Origin")
|
||||
)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.mapParams.containsKey("Destination")) {
|
||||
if (!this.mapParams.get("Destination").equals("Any")) {
|
||||
if (hasParam("Destination")) {
|
||||
if (!getParam("Destination").equals("Any")) {
|
||||
if (!ArrayUtils.contains(
|
||||
this.mapParams.get("Destination").split(","), runParams2.get("Destination")
|
||||
getParam("Destination").split(","), runParams2.get("Destination")
|
||||
)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.mapParams.containsKey("ExcludedDestinations")) {
|
||||
if (hasParam("ExcludedDestinations")) {
|
||||
if (!ArrayUtils.contains(
|
||||
this.mapParams.get("ExcludedDestinations").split(","), runParams2.get("Destination")
|
||||
getParam("ExcludedDestinations").split(","), runParams2.get("Destination")
|
||||
)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.mapParams.containsKey("ValidCard")) {
|
||||
if (hasParam("ValidCard")) {
|
||||
Card moved = (Card) runParams2.get("Card");
|
||||
final Game game = this.getHostCard().getGame();
|
||||
boolean isDiesTrig = "Battlefield".equals(this.mapParams.get("Origin"))
|
||||
&& "Graveyard".equals(this.mapParams.get("Destination"));
|
||||
final Game game = getHostCard().getGame();
|
||||
boolean isDiesTrig = "Battlefield".equals(getParam("Origin"))
|
||||
&& "Graveyard".equals(getParam("Destination"));
|
||||
|
||||
if (isDiesTrig) {
|
||||
moved = game.getChangeZoneLKIInfo(moved);
|
||||
}
|
||||
|
||||
if (!moved.isValid(this.mapParams.get("ValidCard").split(","), this.getHostCard().getController(),
|
||||
this.getHostCard(), null)) {
|
||||
if (!moved.isValid(getParam("ValidCard").split(","), getHostCard().getController(),
|
||||
getHostCard(), null)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasParam("ValidCause")) {
|
||||
if (!runParams2.containsKey("Cause") ) {
|
||||
return false;
|
||||
}
|
||||
SpellAbility cause = (SpellAbility) runParams2.get("Cause");
|
||||
if (!cause.getHostCard().isValid(getParam("ValidCause").split(","), getHostCard().getController(),
|
||||
getHostCard(), null)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check number of lands ETB this turn on triggered card's controller
|
||||
if (mapParams.containsKey("CheckOnTriggeredCard")) {
|
||||
final String[] condition = mapParams.get("CheckOnTriggeredCard").split(" ", 2);
|
||||
if (hasParam("CheckOnTriggeredCard")) {
|
||||
final String[] condition = getParam("CheckOnTriggeredCard").split(" ", 2);
|
||||
|
||||
final Card host = hostCard.getGame().getCardState(hostCard);
|
||||
final String comparator = condition.length < 2 ? "GE1" : condition[1];
|
||||
@@ -128,8 +139,8 @@ public class TriggerChangesZone extends Trigger {
|
||||
}
|
||||
|
||||
// Check amount of damage dealt to the triggered card
|
||||
if (this.mapParams.containsKey("DamageReceivedCondition")) {
|
||||
final String cond = this.mapParams.get("DamageReceivedCondition");
|
||||
if (hasParam("DamageReceivedCondition")) {
|
||||
final String cond = getParam("DamageReceivedCondition");
|
||||
if (cond.length() < 3) {
|
||||
return false;
|
||||
}
|
||||
@@ -152,7 +163,7 @@ public class TriggerChangesZone extends Trigger {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.mapParams.containsKey("OncePerEffect")) {
|
||||
if (hasParam("OncePerEffect")) {
|
||||
// A "once per effect" trigger will only trigger once regardless of how many things the effect caused
|
||||
// to change zones.
|
||||
|
||||
@@ -184,8 +195,8 @@ public class TriggerChangesZone extends Trigger {
|
||||
}
|
||||
|
||||
/* this trigger can only be activated once per turn, verify it hasn't already run */
|
||||
if (this.mapParams.containsKey("ActivationLimit")) {
|
||||
return this.getActivationsThisTurn() < Integer.parseInt(this.mapParams.get("ActivationLimit"));
|
||||
if (hasParam("ActivationLimit")) {
|
||||
return this.getActivationsThisTurn() < Integer.parseInt(getParam("ActivationLimit"));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -13,6 +13,7 @@ import javax.swing.WindowConstants;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
|
||||
import forge.card.CardStateName;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
@@ -165,7 +166,25 @@ public class GuiChoose {
|
||||
if (paper == null) {
|
||||
paper = FModel.getMagicDb().getVariantCards().getUniqueByName(face.getName());
|
||||
}
|
||||
matchUI.setCard(paper);
|
||||
|
||||
if (paper != null && !paper.getName().equals(face.getName())) {
|
||||
Card c = Card.getCardForUi(paper);
|
||||
boolean foundState = false;
|
||||
for (CardStateName cs : c.getStates()) {
|
||||
if (c.getState(cs).getName().equals(face.getName())) {
|
||||
foundState = true;
|
||||
c.setState(cs, true);
|
||||
matchUI.setCard(c.getView());
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!foundState) {
|
||||
matchUI.setCard(paper);
|
||||
}
|
||||
} else {
|
||||
matchUI.setCard(paper);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
Name:Vivien's Invocation
|
||||
ManaCost:5 G G
|
||||
Types:Sorcery
|
||||
A:SP$ PeekAndReveal | Cost$ 4 G G | PeekAmount$ 7 | RememberPeeked$ True | SubAbility$ DBChangeZone | OptionalDecider$ You | Look at the top seven cards of your library. You may put a creature card from among them onto the battlefield. Put the rest on the bottom of your library in a random order. When a creature is put onto the battlefield this way, it deals damage equal to its power to target creature an opponent controls.
|
||||
SVar:DBEffect:DB$ Effect | Name$ Vivien's Invocation Effect | Triggers$ EffTModeChangesZone | RememberObjects$ Remembered.Creature | SVars$ EffTrigDealDamage,EffX | Description$ When a creature is put onto the battlefield this way, it deals damage equal to its power to target creature an opponent controls. | SubAbility$ DBChangeZone
|
||||
SVar:DBChangeZone:DB$ ChangeZone | Origin$ Library | NoLooking$ True | Destination$ Battlefield | LimitSearchLibrary$ Creature.IsRemembered | ChangeValid$ Creature.IsRemembered | Controller$ You | WithoutManaCost$ True | Amount$ 1 | SubAbility$ DBRestRandomOrder
|
||||
SVar:DBRestRandomOrder:DB$ ChangeZone | Defined$ Remembered | AtRandom$ True | Origin$ Library | Destination$ Library | LibraryPosition$ -1
|
||||
SVar:EffTModeChangesZone:Mode$ ChangesZone | ValidCard$ Remembered.Creature | TriggerZones$ Stack | Origin$ Library | Destination$ Battlefield | SubAbility$ EffTrigDealDamage | TriggerDescription$ When a creature is put onto the battlefield this way, it deals damage equal to its power to target creature an opponent controls.
|
||||
SVar:EffTrigDealDamage:DB$ DealDamage | ValidSource$ Remembered+inZoneBattlefield | ValidTgts$ Creature.OppCtrl | TgtPrompt$ Select target creature an opponent controls | NumDmg$ EffX | References$ EffX
|
||||
SVar:EffX:RememberedCard$CardPower
|
||||
Oracle:Look at the top seven cards of your library. You may put a creature card from among them onto the battlefield. Put the rest on the bottom of your library in a random order. When a creature is put onto the battlefield this way, it deals damage equal to its power to target creature an opponent controls.
|
||||
A:SP$ Dig | Cost$ 5 G G | DigNum$ 7 | ChangeNum$ 1 | ChangeValid$ Creature | Optional$ True | RestRandomOrder$ True | DestinationZone$ Battlefield | ForceRevealToController$ True | SpellDescription$ Look at the top seven cards of your library. You may put a creature card from among them onto the battlefield. Put the rest on the bottom of your library in a random order. When a creature is put onto the battlefield this way, it deals damage equals to its power to target creature an opponent controls.
|
||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature | ValidCause$ Card.Self | Execute$ DBDealDamage | Secondary$ True | TriggerDescription$ When a creature is put onto the battlefield this way, it deals damage equals to its power to target creature an opponent controls.
|
||||
SVar:DBDealDamage:DB$ DealDamage | ValidTgts$ Creature.OppCtrl | AILogic$ PowerDmg | TgtPrompt$ Select target creature an opponent controls | NumDmg$ X | References$ X | DamageSource$ TriggeredCard
|
||||
SVar:X:TriggeredCard$CardPower
|
||||
Oracle:Look at the top seven cards of your library. You may put a creature card from among them onto the battlefield. Put the rest on the bottom of your library in a random order. When a creature is put onto the battlefield this way, it deals damage equals to its power to target creature an opponent controls.
|
||||
Reference in New Issue
Block a user