mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-14 17:58:01 +00:00
Handle merged permanent as commander
This commit is contained in:
@@ -132,6 +132,7 @@ public class GameAction {
|
||||
|
||||
Card copied = null;
|
||||
Card lastKnownInfo = null;
|
||||
Card commanderEffect = null; // The effect card of commander replacement effect
|
||||
|
||||
// get the LKI from above like ChangeZoneEffect
|
||||
if (params != null && params.containsKey(AbilityKey.CardLKI)) {
|
||||
@@ -231,6 +232,26 @@ public class GameAction {
|
||||
copied.updateStateForView();
|
||||
|
||||
if (!suppress) {
|
||||
// Temporary disable commander replacement effect
|
||||
// 903.9a
|
||||
if (fromBattlefield && c.isCommander() && c.hasMergedCard()) {
|
||||
// Find the commander replacement effect "card"
|
||||
CardCollectionView comCards = c.getOwner().getCardsIn(ZoneType.Command);
|
||||
for (final Card effCard : comCards) {
|
||||
for (final ReplacementEffect re : effCard.getReplacementEffects()) {
|
||||
if (re.getMode() == ReplacementType.Moved && "Card.EffectSource+YouOwn".equals(re.getParam("ValidCard"))) {
|
||||
commanderEffect = effCard;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (commanderEffect != null) break;
|
||||
}
|
||||
// Disable the commander replacement effect
|
||||
for (final ReplacementEffect re : commanderEffect.getReplacementEffects()) {
|
||||
re.setSuppressed(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (zoneFrom == null) {
|
||||
copied.getOwner().addInboundToken(copied);
|
||||
}
|
||||
@@ -362,12 +383,24 @@ public class GameAction {
|
||||
}
|
||||
}
|
||||
|
||||
// "enter the battlefield as a copy" - apply code here
|
||||
// but how to query for input here and continue later while the callers assume synchronous result?
|
||||
if (mergedCards != null) {
|
||||
// Move components of merged permanet here
|
||||
// Also handle 721.3e and 903.9a
|
||||
boolean wasToken = c.isToken();
|
||||
if (commanderEffect != null) {
|
||||
for (final ReplacementEffect re : commanderEffect.getReplacementEffects()) {
|
||||
re.setSuppressed(false);
|
||||
}
|
||||
}
|
||||
// Change zone of original card so components isToken() and isCommander() return correct value
|
||||
// when running replacement effects here
|
||||
c.setZone(zoneTo);
|
||||
for (final Card card : mergedCards) {
|
||||
// 721.3e
|
||||
if (c.isToken()) {
|
||||
if (card.isRealCommander()) {
|
||||
card.setMoveToCommandZone(true);
|
||||
}
|
||||
// 721.3e & 903.9a
|
||||
if (wasToken && !card.isToken() || card.isRealCommander()) {
|
||||
Map<AbilityKey, Object> repParams = AbilityKey.mapFromAffected(card);
|
||||
repParams.put(AbilityKey.CardLKI, card);
|
||||
repParams.put(AbilityKey.Cause, cause);
|
||||
@@ -389,6 +422,8 @@ public class GameAction {
|
||||
card.setZone(zoneTo);
|
||||
}
|
||||
} else {
|
||||
// "enter the battlefield as a copy" - apply code here
|
||||
// but how to query for input here and continue later while the callers assume synchronous result?
|
||||
zoneTo.add(copied, position, lastKnownInfo); // the modified state of the card is also reported here (e.g. for Morbid + Awaken)
|
||||
c.setZone(zoneTo);
|
||||
}
|
||||
@@ -611,7 +646,7 @@ public class GameAction {
|
||||
AttachEffect.attachAuraOnIndirectEnterBattlefield(c);
|
||||
}
|
||||
|
||||
if (c.isCommander()) {
|
||||
if (c.isRealCommander()) {
|
||||
c.setMoveToCommandZone(true);
|
||||
}
|
||||
|
||||
@@ -1234,7 +1269,7 @@ public class GameAction {
|
||||
}
|
||||
|
||||
private boolean stateBasedAction903_9a(Card c) {
|
||||
if (c.isCommander() && c.canMoveToCommandZone()) {
|
||||
if (c.isRealCommander() && c.canMoveToCommandZone()) {
|
||||
c.setMoveToCommandZone(false);
|
||||
if (c.getOwner().getController().confirmAction(c.getSpellPermanent(), PlayerActionConfirmMode.ChangeZoneToAltDestination, c.getName() + ": If a commander is in a graveyard or in exile and that card was put into that zone since the last time state-based actions were checked, its owner may put it into the command zone.")) {
|
||||
moveTo(c.getOwner().getZone(ZoneType.Command), c, null);
|
||||
|
||||
@@ -80,6 +80,10 @@ public class MutateEffect extends SpellAbilityEffect {
|
||||
host.setFlipped(target.isFlipped());
|
||||
target.setTimesMutated(target.getTimesMutated() + 1);
|
||||
target.updateTokenView();
|
||||
if (host.isCommander()) {
|
||||
target.updateCommanderView();
|
||||
host.getOwner().updateMergedCommanderCast(target, host);
|
||||
}
|
||||
|
||||
game.getTriggerHandler().runTrigger(TriggerType.Mutates, AbilityKey.mapFromCard(target), false);
|
||||
}
|
||||
|
||||
@@ -2757,7 +2757,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
|
||||
// is this "Card" supposed to be a token?
|
||||
public final boolean isToken() {
|
||||
if (hasMergedCard()) {
|
||||
if (isInZone(ZoneType.Battlefield) && hasMergedCard()) {
|
||||
return getTopMergedCard().token;
|
||||
}
|
||||
return token;
|
||||
@@ -6240,6 +6240,13 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
public boolean isCommander() {
|
||||
if (this.getMeldedWith() != null && this.getMeldedWith().isCommander())
|
||||
return true;
|
||||
if (isInZone(ZoneType.Battlefield) && hasMergedCard()) {
|
||||
for (final Card c : getMergedCards())
|
||||
if (c.isCommander) return true;
|
||||
}
|
||||
return isCommander;
|
||||
}
|
||||
public boolean isRealCommander() {
|
||||
return isCommander;
|
||||
}
|
||||
public void setCommander(boolean b) {
|
||||
@@ -6247,6 +6254,9 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
isCommander = b;
|
||||
view.updateCommander(this);
|
||||
}
|
||||
public void updateCommanderView() {
|
||||
view.updateCommander(this);
|
||||
}
|
||||
|
||||
public boolean canMoveToCommandZone() {
|
||||
return canMoveToCommandZone;
|
||||
|
||||
@@ -101,7 +101,7 @@ public class CardFactory {
|
||||
for (final Card o : in.getImprintedCards()) {
|
||||
out.addImprintedCard(o);
|
||||
}
|
||||
out.setCommander(in.isCommander());
|
||||
out.setCommander(in.isRealCommander());
|
||||
//out.setFaceDown(in.isFaceDown());
|
||||
|
||||
return out;
|
||||
|
||||
@@ -2886,6 +2886,10 @@ public class Player extends GameEntity implements Comparable<Player> {
|
||||
getGame().fireEvent(new GameEventPlayerStatsChanged(this, false));
|
||||
}
|
||||
|
||||
public void updateMergedCommanderCast(Card target, Card commander) {
|
||||
getView().updateMergedCommanderCast(this, target, commander);
|
||||
}
|
||||
|
||||
public int getTotalCommanderCast() {
|
||||
int result = 0;
|
||||
for (Integer i : commanderCast.values()) {
|
||||
|
||||
@@ -351,6 +351,15 @@ public class PlayerView extends GameEntityView {
|
||||
set(TrackableProperty.CommanderCast, map);
|
||||
}
|
||||
|
||||
void updateMergedCommanderCast(Player p, Card target, Card commander) {
|
||||
Map<Integer, Integer> map = get(TrackableProperty.CommanderCast);
|
||||
if (map == null) {
|
||||
map = Maps.newHashMap();
|
||||
}
|
||||
map.put(target.getId(), p.getCommanderCast(commander));
|
||||
set(TrackableProperty.CommanderCast, map);
|
||||
}
|
||||
|
||||
public PlayerView getMindSlaveMaster() {
|
||||
return get(TrackableProperty.MindSlaveMaster);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user