mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 12:18:00 +00:00
Add Word of Command
This commit is contained in:
@@ -7,6 +7,7 @@ import forge.game.card.Card;
|
||||
import forge.game.card.CardState;
|
||||
import forge.game.cost.Cost;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.AbilityManaPart;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.staticability.StaticAbility;
|
||||
import forge.util.Expressions;
|
||||
@@ -189,6 +190,18 @@ public class ForgeScript {
|
||||
if (!Expressions.compare(y, property, x)) {
|
||||
return false;
|
||||
}
|
||||
} else if (property.equals("ManaAbilityCantPaidFor")) {
|
||||
if (!sa.isManaAbility()) {
|
||||
return false;
|
||||
}
|
||||
SpellAbility paidFor = sourceController.getPaidForSA();
|
||||
do {
|
||||
AbilityManaPart mana = sa.getManaPart();
|
||||
if (paidFor != null && mana.meetsManaRestrictions(paidFor) && !mana.getExpressChoice().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
sa = sa.getSubAbility();
|
||||
} while(sa != null);
|
||||
} else if (sa.getHostCard() != null) {
|
||||
return sa.getHostCard().hasProperty(property, sourceController, source, spellAbility);
|
||||
}
|
||||
|
||||
@@ -62,6 +62,8 @@ public class PlayEffect extends SpellAbilityEffect {
|
||||
public void resolve(final SpellAbility sa) {
|
||||
final Card source = sa.getHostCard();
|
||||
Player activator = sa.getActivatingPlayer();
|
||||
Player controlledByPlayer = null;
|
||||
long controlledByTimeStamp = -1;
|
||||
final Game game = activator.getGame();
|
||||
final boolean optional = sa.hasParam("Optional");
|
||||
boolean remember = sa.hasParam("RememberPlayed");
|
||||
@@ -74,6 +76,11 @@ public class PlayEffect extends SpellAbilityEffect {
|
||||
activator = AbilityUtils.getDefinedPlayers(source, sa.getParam("Controller"), sa).get(0);
|
||||
}
|
||||
|
||||
if (sa.hasParam("ControlledByPlayer")) {
|
||||
controlledByTimeStamp = game.getNextTimestamp();
|
||||
controlledByPlayer = AbilityUtils.getDefinedPlayers(source, sa.getParam("ControlledByPlayer"), sa).get(0);
|
||||
}
|
||||
|
||||
final Player controller = activator;
|
||||
CardCollection tgtCards;
|
||||
CardCollection showCards = new CardCollection();
|
||||
@@ -164,13 +171,17 @@ public class PlayEffect extends SpellAbilityEffect {
|
||||
amount = tgtCards.size();
|
||||
}
|
||||
|
||||
if (controlledByPlayer != null) {
|
||||
activator.addController(controlledByTimeStamp, controlledByPlayer);
|
||||
}
|
||||
|
||||
final CardCollection saidNoTo = new CardCollection();
|
||||
while (tgtCards.size() > saidNoTo.size() && saidNoTo.size() < amount && amount > 0) {
|
||||
activator.getController().tempShowCards(showCards);
|
||||
Card tgtCard = controller.getController().chooseSingleEntityForEffect(tgtCards, sa, Localizer.getInstance().getMessage("lblSelectCardToPlay"), null);
|
||||
activator.getController().endTempShowCards();
|
||||
if (tgtCard == null) {
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
final boolean wasFaceDown;
|
||||
@@ -300,6 +311,9 @@ public class PlayEffect extends SpellAbilityEffect {
|
||||
|
||||
tgtSA.setSVar("IsCastFromPlayEffect", "True");
|
||||
|
||||
// Add controlled by player to target SA so when the spell is resolving, the controller would be changed again
|
||||
tgtSA.setControlledByPlayer(controlledByTimeStamp, controlledByPlayer);
|
||||
|
||||
if (controller.getController().playSaFromPlayEffect(tgtSA)) {
|
||||
if (remember) {
|
||||
source.addRemembered(tgtSA.getHostCard());
|
||||
@@ -317,6 +331,11 @@ public class PlayEffect extends SpellAbilityEffect {
|
||||
|
||||
amount--;
|
||||
}
|
||||
|
||||
// Remove controlled by player if any
|
||||
if (controlledByPlayer != null) {
|
||||
activator.removeController(controlledByTimeStamp);
|
||||
}
|
||||
} // end resolve
|
||||
|
||||
|
||||
|
||||
@@ -17,10 +17,12 @@
|
||||
*/
|
||||
package forge.game.player;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Deque;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@@ -219,6 +221,8 @@ public class Player extends GameEntity implements Comparable<Player> {
|
||||
private CardCollection lostOwnership = new CardCollection();
|
||||
private CardCollection gainedOwnership = new CardCollection();
|
||||
private int numManaConversion = 0;
|
||||
// The SA currently being paid for
|
||||
private Deque<SpellAbility> paidForStack = new ArrayDeque<>();
|
||||
|
||||
private Card monarchEffect = null;
|
||||
private Card blessingEffect = null;
|
||||
@@ -3281,6 +3285,16 @@ public class Player extends GameEntity implements Comparable<Player> {
|
||||
return view;
|
||||
}
|
||||
|
||||
public SpellAbility getPaidForSA() {
|
||||
return paidForStack.peek();
|
||||
}
|
||||
public void pushPaidForSA(SpellAbility sa) {
|
||||
paidForStack.push(sa);
|
||||
}
|
||||
public void popPaidForSA() {
|
||||
paidForStack.pop();
|
||||
}
|
||||
|
||||
public boolean isMonarch() {
|
||||
return equals(game.getMonarch());
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Iterables;
|
||||
@@ -108,6 +109,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
||||
private ManaCost multiKickerManaCost = null;
|
||||
private Player activatingPlayer = null;
|
||||
private Player targetingPlayer = null;
|
||||
private Pair<Long, Player> controlledByPlayer = null;
|
||||
|
||||
private SpellAbility grantorOriginal = null;
|
||||
private StaticAbility grantorStatic = null;
|
||||
@@ -454,6 +456,24 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
||||
targetingPlayer = targetingPlayer0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return returns who controls the controller of this sa when it is resolving (for Word of Command effect). Null means not being controlled by other
|
||||
*/
|
||||
public Pair<Long, Player> getControlledByPlayer() {
|
||||
return controlledByPlayer;
|
||||
}
|
||||
/**
|
||||
* @param ts time stamp of the control player effect
|
||||
* @param controller the player who will control the controller of this sa
|
||||
*/
|
||||
public void setControlledByPlayer(long ts, Player controller) {
|
||||
if (controller != null) {
|
||||
controlledByPlayer = Pair.of(ts, controller);
|
||||
} else {
|
||||
controlledByPlayer = null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSpell() { return false; }
|
||||
public boolean isAbility() { return true; }
|
||||
public boolean isActivatedAbility() { return false; }
|
||||
|
||||
@@ -479,6 +479,11 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
|
||||
game.copyLastState();
|
||||
}
|
||||
|
||||
// Change controller of activating player if it was set in SA
|
||||
if (sa.getControlledByPlayer() != null) {
|
||||
sa.getActivatingPlayer().addController(sa.getControlledByPlayer().getLeft(), sa.getControlledByPlayer().getRight());
|
||||
}
|
||||
|
||||
if (thisHasFizzled) { // Fizzle
|
||||
if (sa.isBestow()) {
|
||||
// 702.102d: if its target is illegal,
|
||||
@@ -508,6 +513,13 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
|
||||
// do creatures ETB from here?
|
||||
}
|
||||
|
||||
// Change controller back if it was changed
|
||||
if (sa.getControlledByPlayer() != null) {
|
||||
sa.getActivatingPlayer().removeController(sa.getControlledByPlayer().getLeft());
|
||||
// Cleanup controlled by player states
|
||||
sa.setControlledByPlayer(-1, null);
|
||||
}
|
||||
|
||||
game.fireEvent(new GameEventSpellResolved(sa, thisHasFizzled));
|
||||
finishResolving(sa, thisHasFizzled);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user