mirror of
https://github.com/magefree/mage.git
synced 2025-12-22 11:32:00 -08:00
* Fixed a bug that effects where applied to early and often (e.g. dying creature during combat damage step raised Nighthowlers tougness, so he survived lethal damage).
This commit is contained in:
parent
71fb7bf25b
commit
7fc072f467
4 changed files with 68 additions and 21 deletions
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.mage.test.combat;
|
||||||
|
|
||||||
|
import mage.constants.PhaseStep;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that calculated p/t is applied after combat damage resolution, so a 2/2 Nighthowler
|
||||||
|
* dies if blocked from a 2/2 creature.
|
||||||
|
*
|
||||||
|
* @author LevelX2
|
||||||
|
*/
|
||||||
|
public class PowerToughnessCalculationAfterCombatDamageTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void powerToughnessCalculation() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Pain Seer");
|
||||||
|
addCard(Zone.GRAVEYARD, playerA, "Silvercoat Lion");
|
||||||
|
// Nighthowler and enchanted creature each get +X/+X, where X is the number of creature cards in all graveyards.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Nighthowler");
|
||||||
|
addCard(Zone.GRAVEYARD, playerB, "Silvercoat Lion");
|
||||||
|
|
||||||
|
attack(2, playerB, "Nighthowler");
|
||||||
|
block(2, playerA, "Pain Seer", "Nighthowler");
|
||||||
|
|
||||||
|
setStopAt(2, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertLife(playerA, 20);
|
||||||
|
assertLife(playerB, 20);
|
||||||
|
|
||||||
|
assertGraveyardCount(playerB, "Nighthowler", 1);
|
||||||
|
assertGraveyardCount(playerA, "Pain Seer", 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -28,14 +28,17 @@
|
||||||
|
|
||||||
package mage.abilities.effects.common;
|
package mage.abilities.effects.common;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
import mage.MageObject;
|
import mage.MageObject;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.effects.ContinuousEffectImpl;
|
import mage.abilities.effects.ContinuousEffectImpl;
|
||||||
import mage.constants.*;
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Duration;
|
||||||
|
import mage.constants.Layer;
|
||||||
|
import mage.constants.Outcome;
|
||||||
|
import mage.constants.SubLayer;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.game.permanent.PermanentCard;
|
import mage.game.permanent.PermanentCard;
|
||||||
import mage.game.permanent.PermanentToken;
|
import mage.game.permanent.PermanentToken;
|
||||||
|
|
||||||
|
|
@ -50,6 +53,7 @@ public class CopyEffect extends ContinuousEffectImpl<CopyEffect> {
|
||||||
*/
|
*/
|
||||||
private MageObject target;
|
private MageObject target;
|
||||||
private UUID sourceId;
|
private UUID sourceId;
|
||||||
|
private int zoneChangeCounter;
|
||||||
|
|
||||||
public CopyEffect(Permanent target, UUID sourceId) {
|
public CopyEffect(Permanent target, UUID sourceId) {
|
||||||
this(Duration.Custom, target, sourceId);
|
this(Duration.Custom, target, sourceId);
|
||||||
|
|
@ -65,6 +69,16 @@ public class CopyEffect extends ContinuousEffectImpl<CopyEffect> {
|
||||||
super(effect);
|
super(effect);
|
||||||
this.target = effect.target.copy();
|
this.target = effect.target.copy();
|
||||||
this.sourceId = effect.sourceId;
|
this.sourceId = effect.sourceId;
|
||||||
|
this.zoneChangeCounter = effect.zoneChangeCounter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(Ability source, Game game) {
|
||||||
|
super.init(source, game);
|
||||||
|
Permanent permanent = game.getPermanent(sourceId);
|
||||||
|
if (permanent != null) {
|
||||||
|
this.zoneChangeCounter = permanent.getZoneChangeCounter();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -119,12 +133,9 @@ public class CopyEffect extends ContinuousEffectImpl<CopyEffect> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isInactive(Ability source, Game game) {
|
public boolean isInactive(Ability source, Game game) {
|
||||||
// The copy effect is added, if the copy takes place. If source leaves battlefield, the copy effect must cease to exist
|
// The copy effect is added, if the copy takes place. If source left battlefield, the copy effect must cease to exist
|
||||||
Permanent permanent = game.getPermanent(this.sourceId);
|
Permanent permanent = game.getPermanent(this.sourceId);
|
||||||
if (permanent == null) {
|
return permanent == null || permanent.getZoneChangeCounter() != this.zoneChangeCounter;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -461,7 +461,7 @@ public abstract class CardImpl<T extends CardImpl<T>> extends MageObjectImpl<T>
|
||||||
}
|
}
|
||||||
updateZoneChangeCounter();
|
updateZoneChangeCounter();
|
||||||
game.setZone(objectId, event.getToZone());
|
game.setZone(objectId, event.getToZone());
|
||||||
game.fireEvent(event);
|
game.addSimultaneousEvent(event);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -604,7 +604,7 @@ public abstract class CardImpl<T extends CardImpl<T>> extends MageObjectImpl<T>
|
||||||
@Override
|
@Override
|
||||||
public void addInfo(String key, String value) {
|
public void addInfo(String key, String value) {
|
||||||
if (info == null) {
|
if (info == null) {
|
||||||
info = new HashMap<String, String>();
|
info = new HashMap<>();
|
||||||
}
|
}
|
||||||
info.put(key, value);
|
info.put(key, value);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,8 @@ public class PermanentCard extends PermanentImpl<PermanentCard> {
|
||||||
this.rarity = card.getRarity();
|
this.rarity = card.getRarity();
|
||||||
this.cardNumber = card.getCardNumber();
|
this.cardNumber = card.getCardNumber();
|
||||||
this.usesVariousArt = card.getUsesVariousArt();
|
this.usesVariousArt = card.getUsesVariousArt();
|
||||||
|
this.zoneChangeCounter = card.getZoneChangeCounter();
|
||||||
|
|
||||||
canTransform = card.canTransform();
|
canTransform = card.canTransform();
|
||||||
if (canTransform) {
|
if (canTransform) {
|
||||||
secondSideCard = card.getSecondCardFace();
|
secondSideCard = card.getSecondCardFace();
|
||||||
|
|
@ -162,11 +163,6 @@ public class PermanentCard extends PermanentImpl<PermanentCard> {
|
||||||
}
|
}
|
||||||
game.setZone(objectId, event.getToZone());
|
game.setZone(objectId, event.getToZone());
|
||||||
game.addSimultaneousEvent(event);
|
game.addSimultaneousEvent(event);
|
||||||
if (event.getFromZone().equals(Zone.BATTLEFIELD)) {
|
|
||||||
game.getState().handleSimultaneousEvent(game);
|
|
||||||
game.resetForSourceId(getId());
|
|
||||||
game.applyEffects(); // LevelX2: needed to execute isInactive for of custom duration copy effect if source returns directly (e.g. cloudshifted clone)
|
|
||||||
}
|
|
||||||
return game.getState().getZone(objectId) == toZone;
|
return game.getState().getZone(objectId) == toZone;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -193,11 +189,7 @@ public class PermanentCard extends PermanentImpl<PermanentCard> {
|
||||||
game.getExile().createZone(exileId, name).add(card);
|
game.getExile().createZone(exileId, name).add(card);
|
||||||
}
|
}
|
||||||
game.setZone(objectId, event.getToZone());
|
game.setZone(objectId, event.getToZone());
|
||||||
game.fireEvent(event);
|
game.addSimultaneousEvent(event);
|
||||||
if (event.getFromZone().equals(Zone.BATTLEFIELD)) {
|
|
||||||
game.resetForSourceId(getId());
|
|
||||||
game.applyEffects();
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue