mirror of
https://github.com/magefree/mage.git
synced 2026-01-26 21:29:17 -08:00
Fixed a bug that triggred abilities of permanents that were controlled by a player that is not the owner could sometime trigger for a wrong player (Fixes #271).
This commit is contained in:
parent
0751b934ac
commit
857da3a08a
5 changed files with 66 additions and 15 deletions
|
|
@ -53,9 +53,17 @@ public class UndyingTest extends CardTestPlayerBase {
|
|||
*/
|
||||
@Test
|
||||
public void testUndyingEvil() {
|
||||
// Elite Vanguard
|
||||
// Creature — Human Soldier 2/1
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Elite Vanguard");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3);
|
||||
// Last Gasp
|
||||
// Instant, 1B
|
||||
// Target creature gets -3/-3 until end of turn.
|
||||
addCard(Zone.HAND, playerA, "Last Gasp");
|
||||
// Undying Evil
|
||||
// Target creature gains undying until end of turn.
|
||||
// When it dies, if it had no +1/+1 counters on it, return it to the battlefield under its owner's control with a +1/+1 counter on it.)
|
||||
addCard(Zone.HAND, playerA, "Undying Evil");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Last Gasp", "Elite Vanguard");
|
||||
|
|
|
|||
|
|
@ -50,8 +50,19 @@ public class SorinLordOfInnistradTest extends CardTestPlayerBase {
|
|||
|
||||
@Test
|
||||
public void testCard3() {
|
||||
// Sorin, Lord of Innistrad English
|
||||
// Planeswalker — Sorin (Loyalty: 3), 2WB
|
||||
// +1: Put a 1/1 black Vampire creature token with lifelink onto the battlefield.
|
||||
// -2: You get an emblem with "Creatures you control get +1/+0."
|
||||
// -6: Destroy up to three target creatures and/or other planeswalkers. Return each card put into a graveyard this way to the battlefield under your control.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Sorin, Lord of Innistrad");
|
||||
// Craw Wurm
|
||||
// Creature — Wurm 6/4, 4GG
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Craw Wurm");
|
||||
// Angel of Mercy English
|
||||
// Creature — Angel 3/3, 4W (5)
|
||||
// Flying
|
||||
// When Angel of Mercy enters the battlefield, you gain 3 life.
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Angel of Mercy");
|
||||
|
||||
addCounters(1, PhaseStep.UPKEEP, playerA, "Sorin, Lord of Innistrad", CounterType.LOYALTY, 3);
|
||||
|
|
@ -62,8 +73,9 @@ public class SorinLordOfInnistradTest extends CardTestPlayerBase {
|
|||
assertPermanentCount(playerA, "Craw Wurm", 1);
|
||||
assertPermanentCount(playerA, "Angel of Mercy", 1);
|
||||
|
||||
assertLife(playerA, 23);
|
||||
|
||||
assertLife(playerB, 20);
|
||||
assertLife(playerA, 23);
|
||||
assertPermanentCount(playerA, "Sorin, Lord of Innistrad", 0);
|
||||
assertPermanentCount(playerB, "Craw Wurm", 0);
|
||||
assertPermanentCount(playerB, "Angel of Mercy", 0);
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
|
@ -64,7 +65,13 @@ public class TriggeredAbilities extends HashMap<String, TriggeredAbility> {
|
|||
public void checkTriggers(GameEvent event, Game game) {
|
||||
for (TriggeredAbility ability: this.values()) {
|
||||
if (ability.isInUseableZone(game, null, true)) {
|
||||
MageObject object = getMageObject(event, game, ability);
|
||||
MageObject object = null;
|
||||
if (!ability.getZone().equals(Zone.COMMAND) && !game.getState().getZone(ability.getSourceId()).equals(ability.getZone())) {
|
||||
object = game.getShortLivingLKI(ability.getSourceId(), ability.getZone());
|
||||
}
|
||||
if (object == null) {
|
||||
object = getMageObject(event, game, ability);
|
||||
}
|
||||
if (object != null) {
|
||||
if (checkAbilityStillExists(ability, event, object)) {
|
||||
if (object instanceof Permanent) {
|
||||
|
|
|
|||
|
|
@ -127,9 +127,9 @@ public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializa
|
|||
protected transient TableEventSource tableEventSource = new TableEventSource();
|
||||
protected transient PlayerQueryEventSource playerQueryEventSource = new PlayerQueryEventSource();
|
||||
|
||||
protected Map<UUID, Card> gameCards = new HashMap<UUID, Card>();
|
||||
protected Map<UUID, MageObject> lki = new HashMap<UUID, MageObject>();
|
||||
protected Map<UUID, MageObject> shortLivingLKI = new HashMap<UUID, MageObject>();
|
||||
protected Map<UUID, Card> gameCards = new HashMap<UUID, Card>();
|
||||
protected Map<Zone,HashMap<UUID, MageObject>> lki = new EnumMap<Zone, HashMap<UUID, MageObject>>(Zone.class);
|
||||
protected Map<Zone,HashMap<UUID, MageObject>> shortLivingLKI = new EnumMap<Zone, HashMap<UUID, MageObject>>(Zone.class);
|
||||
protected GameState state;
|
||||
|
||||
protected Date startTime;
|
||||
|
|
@ -1763,18 +1763,24 @@ public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializa
|
|||
/*if (!lki.containsKey(objectId)) {
|
||||
return getCard(objectId);
|
||||
}*/
|
||||
MageObject object = lki.get(objectId);
|
||||
if (object != null) {
|
||||
return object.copy();
|
||||
Map<UUID, MageObject> lkiMap = lki.get(zone);
|
||||
if (lkiMap != null) {
|
||||
MageObject object = lkiMap.get(objectId);
|
||||
if (object != null) {
|
||||
return object.copy();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MageObject getShortLivingLKI(UUID objectId, Zone zone) {
|
||||
MageObject object = shortLivingLKI.get(objectId);
|
||||
if (object != null) {
|
||||
return object.copy();
|
||||
Map<UUID, MageObject> shortLivingLkiMap = shortLivingLKI.get(zone);
|
||||
if (shortLivingLkiMap != null) {
|
||||
MageObject object = shortLivingLkiMap.get(objectId);
|
||||
if (object != null) {
|
||||
return object.copy();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
@ -1790,8 +1796,24 @@ public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializa
|
|||
public void rememberLKI(UUID objectId, Zone zone, MageObject object) {
|
||||
if (object instanceof Permanent || object instanceof StackObject) {
|
||||
MageObject copy = object.copy();
|
||||
lki.put(objectId, copy);
|
||||
shortLivingLKI.put(objectId, copy);
|
||||
|
||||
Map<UUID, MageObject> lkiMap = lki.get(zone);
|
||||
if (lkiMap != null) {
|
||||
lkiMap.put(objectId, copy);
|
||||
} else {
|
||||
HashMap<UUID, MageObject> newMap = new HashMap<UUID, MageObject>();
|
||||
newMap.put(objectId, copy);
|
||||
lki.put(zone, newMap);
|
||||
}
|
||||
|
||||
Map<UUID, MageObject> shortLivingLkiMap = shortLivingLKI.get(zone);
|
||||
if (shortLivingLkiMap != null) {
|
||||
shortLivingLkiMap.put(objectId, copy);
|
||||
} else {
|
||||
HashMap<UUID, MageObject> newMap = new HashMap<UUID, MageObject>();
|
||||
newMap.put(objectId, copy);
|
||||
shortLivingLKI.put(zone, newMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -185,6 +185,7 @@ public class PermanentCard extends PermanentImpl<PermanentCard> {
|
|||
Player owner = game.getPlayer(ownerId);
|
||||
game.rememberLKI(objectId, Zone.BATTLEFIELD, this);
|
||||
if (owner != null) {
|
||||
this.setControllerId(ownerId); // neccessary for e.g. abilities in graveyard or hand to not have a controller != owner
|
||||
switch (event.getToZone()) {
|
||||
case GRAVEYARD:
|
||||
owner.putInGraveyard(card, game, !flag);
|
||||
|
|
@ -199,10 +200,11 @@ public class PermanentCard extends PermanentImpl<PermanentCard> {
|
|||
game.addCommander(new Commander(card));
|
||||
break;
|
||||
case LIBRARY:
|
||||
if (flag)
|
||||
if (flag) {
|
||||
owner.getLibrary().putOnTop(card, game);
|
||||
else
|
||||
} else {
|
||||
owner.getLibrary().putOnBottom(card, game);
|
||||
}
|
||||
break;
|
||||
case BATTLEFIELD:
|
||||
//should never happen
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue