Merge branch '1303-control-change-and-cda-not-reset' into 'master'

Resolve "Control Change and CDA not reset?"

Closes #1303

See merge request core-developers/forge!2573
This commit is contained in:
Michael Kamensky
2020-03-01 17:15:39 +00:00
3 changed files with 26 additions and 61 deletions

View File

@@ -565,16 +565,31 @@ public class GameAction {
public final void controllerChangeZoneCorrection(final Card c) {
System.out.println("Correcting zone for " + c.toString());
final Zone oldBattlefield = game.getZoneOf(c);
if (oldBattlefield == null || oldBattlefield.getZoneType() == ZoneType.Stack) {
if (oldBattlefield == null || oldBattlefield.is(ZoneType.Stack)) {
return;
}
final Player original = oldBattlefield.getPlayer();
final PlayerZone newBattlefield = c.getController().getZone(oldBattlefield.getZoneType());
final Player controller = c.getController();
if (original == null || controller == null || original.equals(controller)) {
return;
}
final PlayerZone newBattlefield = controller.getZone(oldBattlefield.getZoneType());
if (newBattlefield == null || oldBattlefield.equals(newBattlefield)) {
return;
}
// 702.94e A paired creature becomes unpaired if any of the following occur:
// another player gains control of it or the creature its paired with
if (c.isPaired()) {
Card partner = c.getPairedWith();
c.setPairedWith(null);
partner.setPairedWith(null);
partner.updateStateForView();
}
game.getTriggerHandler().suppressMode(TriggerType.ChangesZone);
for (Player p : game.getPlayers()) {
((PlayerZoneBattlefield) p.getZone(ZoneType.Battlefield)).setTriggers(false);

View File

@@ -6,7 +6,6 @@ import java.util.List;
import com.google.common.collect.Lists;
import forge.GameCommand;
import forge.card.mana.ManaCost;
import forge.game.Game;
import forge.game.GameEntity;
import forge.game.ability.AbilityUtils;
@@ -18,7 +17,6 @@ import forge.game.combat.Combat;
import forge.game.event.GameEventCardStatsChanged;
import forge.game.event.GameEventCombatChanged;
import forge.game.player.Player;
import forge.game.spellability.Ability;
import forge.game.spellability.SpellAbility;
import forge.game.zone.ZoneType;
import forge.util.collect.FCollectionView;
@@ -26,9 +24,7 @@ import forge.util.Localizer;
import forge.util.CardTranslation;
public class ControlGainEffect extends SpellAbilityEffect {
/* (non-Javadoc)
* @see forge.card.abilityfactory.SpellEffect#getStackDescription(java.util.Map, forge.card.spellability.SpellAbility)
*/
@Override
protected String getStackDescription(SpellAbility sa) {
final StringBuilder sb = new StringBuilder();
@@ -67,15 +63,17 @@ public class ControlGainEffect extends SpellAbilityEffect {
if (null == c || c.hasKeyword("Other players can't gain control of CARDNAME.")) {
return;
}
final Game game = host.getGame();
if (c.isInPlay()) {
c.removeTempController(tStamp);
game.getAction().controllerChangeZoneCorrection(c);
if (tapOnLose) {
c.tap();
}
} // if
host.removeGainControlTargets(c);
}
@Override
@@ -84,11 +82,9 @@ public class ControlGainEffect extends SpellAbilityEffect {
final boolean bUntap = sa.hasParam("Untap");
final boolean bTapOnLose = sa.hasParam("TapOnLose");
final boolean bNoRegen = sa.hasParam("NoRegen");
final boolean remember = sa.hasParam("RememberControlled");
final boolean forget = sa.hasParam("ForgetControlled");
final boolean attacking = sa.hasParam("Attacking");
final List<String> destroyOn = sa.hasParam("DestroyTgt") ? Arrays.asList(sa.getParam("DestroyTgt").split(",")) : null;
final List<String> keywords = sa.hasParam("AddKWs") ? Arrays.asList(sa.getParam("AddKWs").split(" & ")) : null;
final List<String> lose = sa.hasParam("LoseControl") ? Arrays.asList(sa.getParam("LoseControl").split(",")) : null;
@@ -189,18 +185,6 @@ public class ControlGainEffect extends SpellAbilityEffect {
}
}
if (destroyOn != null) {
if (destroyOn.contains("LeavesPlay")) {
sa.getHostCard().addLeavesPlayCommand(getDestroyCommand(tgtC, source, bNoRegen));
}
if (destroyOn.contains("Untap")) {
sa.getHostCard().addUntapCommand(getDestroyCommand(tgtC, source, bNoRegen));
}
if (destroyOn.contains("LoseControl")) {
sa.getHostCard().addChangeControllerCommand(getDestroyCommand(tgtC, source, bNoRegen));
}
}
if (keywords != null) {
// Add keywords only until end of turn
final GameCommand untilKeywordEOT = new GameCommand() {
@@ -241,43 +225,6 @@ public class ControlGainEffect extends SpellAbilityEffect {
} // end foreach target
}
/**
* <p>
* getDestroyCommand.
* </p>
*
* @param i
* a int.
* @return a {@link forge.GameCommand} object.
*/
private static GameCommand getDestroyCommand(final Card c, final Card hostCard, final boolean bNoRegen) {
final GameCommand destroy = new GameCommand() {
private static final long serialVersionUID = 878543373519872418L;
@Override
public void run() {
final Game game = hostCard.getGame();
final Ability ability = new Ability(hostCard, ManaCost.ZERO) {
@Override
public void resolve() {
game.getAction().destroy(c, null, !bNoRegen, null);
}
};
final StringBuilder sb = new StringBuilder();
sb.append(hostCard).append(" - destroy ").append(c.getName()).append(".");
if (bNoRegen) {
sb.append(" It can't be regenerated.");
}
ability.setStackDescription(sb.toString());
ability.setTrigger(true);
game.getStack().addSimultaneousStackEntry(ability);
}
};
return destroy;
}
/**
* <p>
* getLoseControlCommand.

View File

@@ -3,6 +3,9 @@ ManaCost:W U B
Types:Legendary Creature Human
PT:1/1
K:CARDNAME doesn't untap during your untap step.
A:AB$ GainControl | Cost$ T | ValidTgts$ Creature | TgtPrompt$ Select target creature | LoseControl$ LeavesPlay,LoseControl | DestroyTgt$ LeavesPlay,LoseControl,Untap | NoRegen$ True | SpellDescription$ Gain control of target creature for as long as you control CARDNAME. When CARDNAME leaves the battlefield or becomes untapped, destroy that creature. It can't be regenerated.
SVar:Picture:http://www.wizards.com/global/images/magic/general/merieke_ri_berit.jpg
A:AB$ GainControl | Cost$ T | ValidTgts$ Creature | TgtPrompt$ Select target creature | LoseControl$ LeavesPlay,LoseControl | SubAbility$ DBEffect | SpellDescription$ Gain control of target creature for as long as you control CARDNAME. When CARDNAME leaves the battlefield or becomes untapped, destroy that creature. It can't be regenerated.
SVar:DBEffect:DB$ Effect | RememberObjects$ ParentTarget | ForgetOnMoved$ Battlefield | Triggers$ LeavesPlay,Untap | References$ LeavesPlay,Untap | Duration$ UntilHostLeavesPlay
SVar:LeavesPlay:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Any | ValidCard$ Card.EffectSource | Execute$ DBDestroy | TriggerDescription$ When EFFECTSOURCE leaves the battlefield, or becomes untapped, destroy that creature. It can't be regenerated.
SVar:Untap:Mode$ Untaps | ValidCard$ Card.EffectSource | Execute$ DBDestroy | Secondary$ True | TriggerDescription$ When EFFECTSOURCE leaves the battlefield, or becomes untapped, destroy that creature. It can't be regenerated.
SVar:DBDestroy:DB$ Destroy | Defined$ Remembered | NoRegen$ True
Oracle:Merieke Ri Berit doesn't untap during your untap step.\n{T}: Gain control of target creature for as long as you control Merieke Ri Berit. When Merieke Ri Berit leaves the battlefield or becomes untapped, destroy that creature. It can't be regenerated.