mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 19:58:00 +00:00
Big MayPlay rewrite, now use StaticAbility as Key in the mayPlay Map
SpellAbilityRestriction now does check if the spell is still valid when playing. Add Special Logic for Bestow spells there. MayPlay that only allows creature spells, can't be used for Bestow.
This commit is contained in:
@@ -884,7 +884,7 @@ public class AiController {
|
||||
}
|
||||
// move snap-casted spells to front
|
||||
if (source.isInZone(ZoneType.Graveyard)) {
|
||||
if(sa.getMayPlayHost() != null && source.mayPlay(sa.getMayPlayHost()) != null) {
|
||||
if(sa.getMayPlay() != null && source.mayPlay(sa.getMayPlay()) != null) {
|
||||
p += 50;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1516,10 +1516,10 @@ public class ComputerUtil {
|
||||
ComputerUtilCombat.combatantWouldBeDestroyed(ai, source, game.getCombat())) {
|
||||
return true;
|
||||
}
|
||||
} else if (zone.getZoneType() == ZoneType.Exile && sa.getMayPlayHost() != null) {
|
||||
} else if (zone.getZoneType() == ZoneType.Exile && sa.getMayPlay() != null) {
|
||||
// play cards in exile that can only be played that turn
|
||||
if (game.getPhaseHandler().getPhase() == PhaseType.MAIN2) {
|
||||
if (source.mayPlay(sa.getMayPlayHost()) != null) {
|
||||
if (source.mayPlay(sa.getMayPlay()) != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,7 +191,7 @@ public final class GameActionUtil {
|
||||
}
|
||||
sar.setZone(null);
|
||||
newSA.setRestrictions(sar);
|
||||
newSA.setMayPlayHost(host);
|
||||
newSA.setMayPlay(o.getAbility());
|
||||
if (o.getPayManaCost() == PayManaCost.NO) {
|
||||
newSA.setBasicSpell(false);
|
||||
newSA.setPayCosts(newSA.getPayCosts().copyWithNoMana());
|
||||
|
||||
@@ -46,6 +46,7 @@ import com.google.common.collect.Maps;
|
||||
public class StaticEffect {
|
||||
|
||||
private final Card source;
|
||||
private StaticAbility ability;
|
||||
private int keywordNumber = 0;
|
||||
private CardCollectionView affectedCards = new CardCollection();
|
||||
private List<Player> affectedPlayers = Lists.newArrayList();
|
||||
@@ -83,8 +84,14 @@ public class StaticEffect {
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
StaticEffect(final StaticAbility ability) {
|
||||
this(ability.getHostCard());
|
||||
this.ability = ability;
|
||||
}
|
||||
|
||||
private StaticEffect makeMappedCopy(GameObjectMap map) {
|
||||
StaticEffect copy = new StaticEffect(map.map(this.source));
|
||||
copy.ability = this.ability;
|
||||
copy.keywordNumber = this.keywordNumber;
|
||||
copy.affectedCards = map.mapCollection(this.affectedCards);
|
||||
copy.affectedPlayers = map.mapList(this.affectedPlayers);
|
||||
@@ -1046,7 +1053,7 @@ public class StaticEffect {
|
||||
affectedCard.setMayLookAt(controller, false);
|
||||
}
|
||||
if (removeMayPlay) {
|
||||
affectedCard.removeMayPlay(source);
|
||||
affectedCard.removeMayPlay(ability);
|
||||
}
|
||||
affectedCard.updateStateForView();
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ public class StaticEffects {
|
||||
return currentEffect;
|
||||
}
|
||||
|
||||
final StaticEffect newEffect = new StaticEffect(staticAbility.getHostCard());
|
||||
final StaticEffect newEffect = new StaticEffect(staticAbility);
|
||||
this.staticEffects.put(staticAbility, newEffect);
|
||||
return newEffect;
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
private GameEntity enchanting = null;
|
||||
private GameEntity mustAttackEntity = null;
|
||||
|
||||
private final Map<Card, CardPlayOption> mayPlay = Maps.newTreeMap();
|
||||
private final Map<StaticAbility, CardPlayOption> mayPlay = Maps.newTreeMap();
|
||||
private int mayPlayTurn = 0;
|
||||
|
||||
// changes by AF animate and continuous static effects - timestamp is the key of maps
|
||||
@@ -2271,11 +2271,11 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
view.setPlayerMayLook(player, mayLookAt, temp);
|
||||
}
|
||||
|
||||
public final CardPlayOption mayPlay(final Card host) {
|
||||
if (host == null) {
|
||||
public final CardPlayOption mayPlay(final StaticAbility sta) {
|
||||
if (sta == null) {
|
||||
return null;
|
||||
}
|
||||
return mayPlay.get(host);
|
||||
return mayPlay.get(sta);
|
||||
}
|
||||
public final List<CardPlayOption> mayPlay(final Player player) {
|
||||
List<CardPlayOption> result = Lists.newArrayList();
|
||||
@@ -2286,11 +2286,11 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public final void setMayPlay(final Player player, final boolean withoutManaCost, final boolean ignoreColor, final boolean withFlash, final Card host) {
|
||||
this.mayPlay.put(host, new CardPlayOption(player, host, withoutManaCost, ignoreColor, withFlash));
|
||||
public final void setMayPlay(final Player player, final boolean withoutManaCost, final boolean ignoreColor, final boolean withFlash, final StaticAbility sta) {
|
||||
this.mayPlay.put(sta, new CardPlayOption(player, sta, withoutManaCost, ignoreColor, withFlash));
|
||||
}
|
||||
public final void removeMayPlay(final Card host) {
|
||||
this.mayPlay.remove(host);
|
||||
public final void removeMayPlay(final StaticAbility sta) {
|
||||
this.mayPlay.remove(sta);
|
||||
}
|
||||
|
||||
public int getMayPlayTurn() {
|
||||
|
||||
@@ -3,6 +3,7 @@ package forge.game.card;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import forge.game.player.Player;
|
||||
import forge.game.staticability.StaticAbility;
|
||||
|
||||
public final class CardPlayOption {
|
||||
public enum PayManaCost {
|
||||
@@ -13,17 +14,17 @@ public final class CardPlayOption {
|
||||
}
|
||||
|
||||
private final Player player;
|
||||
private final Card host;
|
||||
private final StaticAbility sta;
|
||||
private final PayManaCost payManaCost;
|
||||
private final boolean ignoreManaCostColor;
|
||||
private final boolean withFlash;
|
||||
|
||||
public CardPlayOption(final Player player, final Card host, final boolean withoutManaCost, final boolean ignoreManaCostColor, final boolean withFlash) {
|
||||
this(player, host, withoutManaCost ? PayManaCost.NO : PayManaCost.YES, ignoreManaCostColor, withFlash);
|
||||
public CardPlayOption(final Player player, final StaticAbility sta, final boolean withoutManaCost, final boolean ignoreManaCostColor, final boolean withFlash) {
|
||||
this(player, sta, withoutManaCost ? PayManaCost.NO : PayManaCost.YES, ignoreManaCostColor, withFlash);
|
||||
}
|
||||
private CardPlayOption(final Player player, final Card host, final PayManaCost payManaCost, final boolean ignoreManaCostColor, final boolean withFlash) {
|
||||
private CardPlayOption(final Player player, final StaticAbility sta, final PayManaCost payManaCost, final boolean ignoreManaCostColor, final boolean withFlash) {
|
||||
this.player = player;
|
||||
this.host = host;
|
||||
this.sta = sta;
|
||||
this.payManaCost = payManaCost;
|
||||
this.ignoreManaCostColor = ignoreManaCostColor;
|
||||
this.withFlash = withFlash;
|
||||
@@ -35,7 +36,11 @@ public final class CardPlayOption {
|
||||
}
|
||||
|
||||
public Card getHost() {
|
||||
return host;
|
||||
return sta.getHostCard();
|
||||
}
|
||||
|
||||
public StaticAbility getAbility() {
|
||||
return sta;
|
||||
}
|
||||
|
||||
public PayManaCost getPayManaCost() {
|
||||
|
||||
@@ -36,6 +36,7 @@ import forge.game.cost.CostPart;
|
||||
import forge.game.cost.CostPartMana;
|
||||
import forge.game.mana.Mana;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.staticability.StaticAbility;
|
||||
import forge.game.trigger.TriggerType;
|
||||
import forge.game.trigger.WrappedAbility;
|
||||
import forge.util.Expressions;
|
||||
@@ -141,7 +142,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
||||
|
||||
private SpellAbilityView view;
|
||||
|
||||
private Card mayPlay = null;
|
||||
private StaticAbility mayPlay = null;
|
||||
|
||||
protected SpellAbility(final Card iSourceCard, final Cost toPay) {
|
||||
this(iSourceCard, toPay, null);
|
||||
@@ -584,11 +585,11 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
||||
outlast = outlast0;
|
||||
}
|
||||
|
||||
public Card getMayPlayHost() {
|
||||
public StaticAbility getMayPlay() {
|
||||
return mayPlay;
|
||||
}
|
||||
public void setMayPlayHost(final Card host) {
|
||||
mayPlay = host;
|
||||
public void setMayPlay(final StaticAbility sta) {
|
||||
mayPlay = sta;
|
||||
}
|
||||
|
||||
public boolean isLeftSplit() {
|
||||
|
||||
@@ -28,6 +28,7 @@ import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardFactoryUtil;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPlayOption;
|
||||
import forge.game.card.CardUtil;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.zone.Zone;
|
||||
@@ -201,26 +202,39 @@ public class SpellAbilityRestriction extends SpellAbilityVariables {
|
||||
* @return a boolean.
|
||||
*/
|
||||
public final boolean checkZoneRestrictions(final Card c, final SpellAbility sa) {
|
||||
if (this.getZone() == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final Player activator = sa.getActivatingPlayer();
|
||||
final Zone cardZone = activator.getGame().getZoneOf(c);
|
||||
if (cardZone == null || !cardZone.is(this.getZone())) {
|
||||
Card cp = c;
|
||||
|
||||
// for Bestow need to check the animated State
|
||||
if (sa.isSpell() && sa.hasParam("Bestow")) {
|
||||
cp = CardUtil.getLKICopy(c);
|
||||
cp.animateBestow();
|
||||
}
|
||||
|
||||
if (cardZone == null || this.getZone() == null || !cardZone.is(this.getZone())) {
|
||||
// If Card is not in the default activating zone, do some additional checks
|
||||
// Not a Spell, or on Battlefield, return false
|
||||
if (!sa.isSpell() || (cardZone != null && ZoneType.Battlefield.equals(cardZone.getZoneType()))
|
||||
|| !this.getZone().equals(ZoneType.Hand)) {
|
||||
|| (this.getZone() != null && !this.getZone().equals(ZoneType.Hand))) {
|
||||
return false;
|
||||
}
|
||||
if (cardZone != null && cardZone.is(ZoneType.Stack)) {
|
||||
return false;
|
||||
}
|
||||
if (sa.isSpell()) {
|
||||
final CardPlayOption o = c.mayPlay(sa.getMayPlayHost());
|
||||
final CardPlayOption o = c.mayPlay(sa.getMayPlay());
|
||||
if (o != null && o.getPlayer() == activator) {
|
||||
return true;
|
||||
Map<String,String> params = sa.getMayPlay().getMapParams();
|
||||
|
||||
if (params.containsKey("Affected")) {
|
||||
if (!cp.isValid(params.get("Affected"), activator, o.getHost(), null)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@@ -301,7 +315,7 @@ public class SpellAbilityRestriction extends SpellAbilityVariables {
|
||||
}
|
||||
|
||||
if (sa.isSpell()) {
|
||||
final CardPlayOption o = c.mayPlay(sa.getMayPlayHost());
|
||||
final CardPlayOption o = c.mayPlay(sa.getMayPlay());
|
||||
if (o != null && o.getPlayer() == activator) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ import com.google.common.collect.Maps;
|
||||
/**
|
||||
* The Class StaticAbility.
|
||||
*/
|
||||
public class StaticAbility extends CardTraitBase {
|
||||
public class StaticAbility extends CardTraitBase implements Comparable<StaticAbility> {
|
||||
|
||||
private final Set<StaticAbilityLayer> layers;
|
||||
private CardCollectionView ignoreEffectCards = new CardCollection();
|
||||
@@ -620,4 +620,8 @@ public class StaticAbility extends CardTraitBase {
|
||||
return layers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(StaticAbility arg0) {
|
||||
return getHostCard().compareTo(arg0.getHostCard());
|
||||
}
|
||||
} // end class StaticAbility
|
||||
|
||||
@@ -617,7 +617,7 @@ public final class StaticAbilityContinuous {
|
||||
}
|
||||
if (controllerMayPlay && (mayPlayLimit == null || hostCard.getMayPlayTurn() < mayPlayLimit)) {
|
||||
Player mayPlayController = params.containsKey("MayPlayCardOwner") ? affectedCard.getOwner() : controller;
|
||||
affectedCard.setMayPlay(mayPlayController, mayPlayWithoutManaCost, mayPlayIgnoreColor, mayPlayWithFlash, hostCard);
|
||||
affectedCard.setMayPlay(mayPlayController, mayPlayWithoutManaCost, mayPlayIgnoreColor, mayPlayWithFlash, stAb);
|
||||
}
|
||||
|
||||
affectedCard.updateStateForView();
|
||||
|
||||
@@ -451,8 +451,8 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
|
||||
System.out.println(sp.getHostCard().getName() + " - activatingPlayer not set before adding to stack.");
|
||||
}
|
||||
|
||||
if (sp.isSpell() && sp.getMayPlayHost() != null) {
|
||||
sp.getMayPlayHost().incMayPlayTurn();
|
||||
if (sp.isSpell() && sp.getMayPlay() != null) {
|
||||
sp.getMayPlay().getHostCard().incMayPlayTurn();
|
||||
}
|
||||
final SpellAbilityStackInstance si = new SpellAbilityStackInstance(sp);
|
||||
|
||||
|
||||
@@ -63,13 +63,18 @@ public class PlayerZone extends Zone {
|
||||
|
||||
for (final SpellAbility sa : c.getSpellAbilities()) {
|
||||
final ZoneType restrictZone = sa.getRestrictions().getZone();
|
||||
|
||||
// for mayPlay the restrictZone is null for reasons
|
||||
if (sa.isSpell() && c.mayPlay(sa.getMayPlay()) != null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (PlayerZone.this.is(restrictZone)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (sa.isSpell()
|
||||
&& (c.mayPlay(sa.getMayPlayHost()) != null
|
||||
|| (c.hasStartOfKeyword("Flashback") && PlayerZone.this.is(ZoneType.Graveyard)))
|
||||
&& (c.hasStartOfKeyword("Flashback") && PlayerZone.this.is(ZoneType.Graveyard))
|
||||
&& restrictZone.equals(ZoneType.Hand)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user