mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 11:48:02 +00:00
- Converted "You may discard CARDNAME any time you could cast an instant." to script
This commit is contained in:
@@ -45,6 +45,7 @@ public final class AbilityFactory {
|
||||
public enum AbilityRecordType {
|
||||
Ability("AB"),
|
||||
Spell("SP"),
|
||||
StaticAbility("ST"),
|
||||
SubAbility("DB");
|
||||
|
||||
private final String prefix;
|
||||
@@ -59,6 +60,7 @@ public final class AbilityFactory {
|
||||
switch(this) {
|
||||
case Ability: return new AbilityApiBased(api, hostCard, abCost, abTgt, mapParams);
|
||||
case Spell: return new SpellApiBased(api, hostCard, abCost, abTgt, mapParams);
|
||||
case StaticAbility: return new StaticAbilityApiBased(api, hostCard, abCost, abTgt, mapParams);
|
||||
case SubAbility: return new AbilitySub(api, hostCard, abTgt, mapParams);
|
||||
}
|
||||
return null; // exception here would be fine!
|
||||
@@ -73,6 +75,8 @@ public final class AbilityFactory {
|
||||
return AbilityRecordType.Ability;
|
||||
} else if (abParams.containsKey(AbilityRecordType.Spell.getPrefix())) {
|
||||
return AbilityRecordType.Spell;
|
||||
} else if (abParams.containsKey(AbilityRecordType.StaticAbility.getPrefix())) {
|
||||
return AbilityRecordType.StaticAbility;
|
||||
} else if (abParams.containsKey(AbilityRecordType.SubAbility.getPrefix())) {
|
||||
return AbilityRecordType.SubAbility;
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package forge.game.ability;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.ability.effects.ChangeZoneAllEffect;
|
||||
import forge.game.ability.effects.ChangeZoneEffect;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.cost.Cost;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.AbilityStatic;
|
||||
import forge.game.spellability.TargetRestrictions;
|
||||
|
||||
public class StaticAbilityApiBased extends AbilityStatic {
|
||||
|
||||
private final SpellAbilityEffect effect;
|
||||
private final SpellAbilityAi ai;
|
||||
|
||||
public StaticAbilityApiBased(ApiType api0, Card sourceCard, Cost abCost, TargetRestrictions tgt, Map<String, String> params0) {
|
||||
super(sourceCard, abCost, tgt);
|
||||
params = params0;
|
||||
api = api0;
|
||||
effect = api.getSpellEffect();
|
||||
ai = api.getAi();
|
||||
|
||||
if (effect instanceof ChangeZoneEffect || effect instanceof ChangeZoneAllEffect) {
|
||||
AbilityFactory.adjustChangeZoneTarget(params, this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStackDescription() {
|
||||
return effect.getStackDescriptionWithSubs(params, this);
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.spellability.SpellAbility#resolve()
|
||||
*/
|
||||
@Override
|
||||
public void resolve() {
|
||||
effect.resolve(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPlayAI(Player aiPlayer) {
|
||||
return ai.canPlayAIWithSubs(aiPlayer, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doTrigger(final boolean mandatory, Player aiPlayer) {
|
||||
return ai.doTriggerAI(aiPlayer, this, mandatory);
|
||||
}
|
||||
}
|
||||
@@ -102,15 +102,20 @@ public class DiscardEffect extends SpellAbilityEffect {
|
||||
}
|
||||
final int numCardsInHand = p.getCardsIn(ZoneType.Hand).size();
|
||||
if (mode.equals("Defined")) {
|
||||
final List<Card> toDiscard = AbilityUtils.getDefinedCards(source, sa.getParam("DefinedCards"), sa);
|
||||
for (final Card c : toDiscard) {
|
||||
boolean hasDiscarded = p.discard(c, sa);
|
||||
if(hasDiscarded)
|
||||
discarded.add(c);
|
||||
}
|
||||
if (sa.hasParam("RememberDiscarded")) {
|
||||
for (final Card c : discarded) {
|
||||
source.addRemembered(c);
|
||||
boolean runDiscard = !sa.hasParam("Optional") || p.getController().confirmAction(sa, PlayerActionConfirmMode.Random, sa.getParam("DiscardMessage"));
|
||||
if (runDiscard) {
|
||||
final List<Card> toDiscard = AbilityUtils.getDefinedCards(source, sa.getParam("DefinedCards"), sa);
|
||||
for (final Card c : toDiscard) {
|
||||
boolean hasDiscarded = p.discard(c, sa);
|
||||
if (hasDiscarded) {
|
||||
discarded.add(c);
|
||||
}
|
||||
}
|
||||
|
||||
if (sa.hasParam("RememberDiscarded")) {
|
||||
for (final Card c : discarded) {
|
||||
source.addRemembered(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
|
||||
@@ -1959,8 +1959,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
|| keyword.startsWith("PreventAllDamageBy")
|
||||
|| keyword.startsWith("CantBlock")
|
||||
|| keyword.startsWith("CantEquip")
|
||||
|| keyword.startsWith("SpellCantTarget")
|
||||
|| keyword.equals("MayDiscardFromHand")) {
|
||||
|| keyword.startsWith("SpellCantTarget")) {
|
||||
continue;
|
||||
}
|
||||
if (keyword.startsWith("etbCounter")) {
|
||||
|
||||
@@ -3193,10 +3193,6 @@ public class CardFactoryUtil {
|
||||
}
|
||||
} // Morph
|
||||
|
||||
if (hasKeyword(card, "MayDiscardFromHand") != -1) {
|
||||
card.addSpellAbility(abilityDiscardSource(card)); // Circling Vultures
|
||||
}
|
||||
|
||||
if (hasKeyword(card, "Unearth") != -1) {
|
||||
final int n = hasKeyword(card, "Unearth");
|
||||
if (n != -1) {
|
||||
@@ -3451,42 +3447,6 @@ public class CardFactoryUtil {
|
||||
} // Ripple
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this method.
|
||||
* @param card
|
||||
* @return
|
||||
*/
|
||||
public static AbilityStatic abilityDiscardSource(final Card sourceCard) {
|
||||
final AbilityStatic discard = new AbilityStatic(sourceCard, new Cost("0", true), null) {
|
||||
@Override
|
||||
public void resolve() {
|
||||
if (this.getActivatingPlayer().getController().confirmAction(this, null, "Discard this card?")) {
|
||||
this.getActivatingPlayer().discard(sourceCard, this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPlay() {
|
||||
return sourceCard.isInZone(ZoneType.Hand)
|
||||
&& sourceCard.getController().equals(this.getActivatingPlayer());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPlayAI(Player aiPlayer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("You may discard ").append(sourceCard.getName());
|
||||
sb.append(" any time you could cast an instant.");
|
||||
discard.setDescription(sb.toString());
|
||||
|
||||
final StringBuilder sbStack = new StringBuilder();
|
||||
sbStack.append(sourceCard.getName()).append(" - discard this card.");
|
||||
discard.setStackDescription(sbStack.toString());
|
||||
return discard;
|
||||
}
|
||||
|
||||
public final static void refreshTotemArmor(Card c) {
|
||||
boolean hasKw = c.hasKeyword("Totem armor");
|
||||
|
||||
@@ -20,6 +20,7 @@ package forge.game.spellability;
|
||||
import forge.card.mana.ManaCost;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.cost.Cost;
|
||||
import forge.game.player.Player;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -50,4 +51,15 @@ public abstract class AbilityStatic extends Ability {
|
||||
this.setTargetRestrictions(tgt);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public boolean canPlay() {
|
||||
Player player = getActivatingPlayer();
|
||||
if (player == null) {
|
||||
player = this.getSourceCard().getController();
|
||||
}
|
||||
|
||||
final Card c = this.getSourceCard();
|
||||
|
||||
return this.getRestrictions().canPlay(c, this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -340,7 +340,7 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
|
||||
|
||||
if ((sp instanceof AbilityTriggered) || (sp instanceof AbilityStatic)) {
|
||||
// TODO: make working triggered ability
|
||||
sp.resolve();
|
||||
AbilityUtils.resolve(sp);
|
||||
} else {
|
||||
for (OptionalCost s : sp.getOptionalCosts()) {
|
||||
source.addOptionalCostPaid(s);
|
||||
|
||||
Reference in New Issue
Block a user