Merge remote-tracking branch 'remotes/core/master'

This commit is contained in:
Anthony Calosa
2021-04-16 13:30:25 +08:00
12 changed files with 80 additions and 23 deletions

View File

@@ -1029,7 +1029,7 @@ public class PlayerControllerAi extends PlayerController {
*/
if (sa.isMayChooseNewTargets() && !sa.setupTargets()) {
if (sa.isSpell()) {
sa.getHostCard().ceaseToExist();
sa.getHostCard().ceaseToExist(false);
}
continue;
}

View File

@@ -769,12 +769,19 @@ public class Game {
p.revealFaceDownCards();
}
for(Card c : cards) {
for (Card c : cards) {
// CR 800.4d if card is controlled by opponent, LTB should trigger
if (c.getOwner().equals(p) && c.getController().equals(p)) {
c.getCurrentState().clearTriggers();
}
}
for (Card c : cards) {
if (c.getController().equals(p) && (c.isPlane() || c.isPhenomenon())) {
planarControllerLost = true;
}
if(isMultiplayer) {
if (isMultiplayer) {
// unattach all "Enchant Player"
c.removeAttachedTo(p);
if (c.getOwner().equals(p)) {
@@ -783,7 +790,9 @@ public class Game {
cc.removeEncodedCard(c);
cc.removeRemembered(c);
}
c.ceaseToExist();
c.ceaseToExist(false);
// CR 603.2f owner of trigger source lost game
triggerHandler.clearDelayedTrigger(c);
} else {
// return stolen permanents
if (c.getController().equals(p) && c.isInZone(ZoneType.Battlefield)) {

View File

@@ -6756,11 +6756,15 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
}
}
public void ceaseToExist() {
getGame().getTriggerHandler().suppressMode(TriggerType.ChangesZone);
getZone().remove(this);
setZone(null);
getGame().getTriggerHandler().clearSuppression(TriggerType.ChangesZone);
public void ceaseToExist(boolean skipTrig) {
// CR 603.6c other players LTB triggers should work
if (skipTrig) {
getZone().remove(this);
setZone(getOwner().getZone(ZoneType.None));
}
else {
game.getAction().moveTo(ZoneType.None, this, null);
}
}
public void forceTurnFaceUp() {

View File

@@ -133,7 +133,7 @@ import forge.util.collect.FCollectionView;
public class Player extends GameEntity implements Comparable<Player> {
public static final List<ZoneType> ALL_ZONES = Collections.unmodifiableList(Arrays.asList(ZoneType.Battlefield,
ZoneType.Library, ZoneType.Graveyard, ZoneType.Hand, ZoneType.Exile, ZoneType.Command, ZoneType.Ante,
ZoneType.Sideboard, ZoneType.PlanarDeck, ZoneType.SchemeDeck, ZoneType.Merged, ZoneType.Subgame));
ZoneType.Sideboard, ZoneType.PlanarDeck, ZoneType.SchemeDeck, ZoneType.Merged, ZoneType.Subgame, ZoneType.None));
private final Map<Card, Integer> commanderDamage = Maps.newHashMap();

View File

@@ -2361,7 +2361,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
public void rollback() {
for (Card c : rollbackEffects) {
c.ceaseToExist();
c.ceaseToExist(true);
}
rollbackEffects.clear();
}

View File

@@ -882,6 +882,17 @@ public final class StaticAbilityContinuous {
affectedCard.setMayPlay(mayPlayController, mayPlayWithoutManaCost,
mayPlayAltCost != null ? new Cost(mayPlayAltCost, false) : null,
mayPlayWithFlash, mayPlayGrantZonePermissions, stAb);
// If the MayPlay effect only affected itself, check if it is in graveyard and give other player who cast Shaman's Trance MayPlay
if (stAb.getParam("Affected").equals("Card.Self") && affectedCard.isInZone(ZoneType.Graveyard)) {
for (final Player p : game.getPlayers()) {
if (p.hasKeyword("Shaman's Trance") && mayPlayController != p) {
affectedCard.setMayPlay(p, mayPlayWithoutManaCost,
mayPlayAltCost != null ? new Cost(mayPlayAltCost, false) : null,
mayPlayWithFlash, mayPlayGrantZonePermissions, stAb);
}
}
}
}
}
@@ -979,7 +990,26 @@ public final class StaticAbilityContinuous {
affectedCards.addAll(game.getCardsIn(ZoneType.Battlefield));
}
if (stAb.hasParam("Affected")) {
// Handle Shaman's Trance
CardCollection affectedCardsOriginal = null;
if (controller.hasKeyword("Shaman's Trance") && stAb.hasParam("MayPlay")) {
affectedCardsOriginal = new CardCollection(affectedCards);
}
affectedCards = CardLists.getValidCards(affectedCards, stAb.getParam("Affected").split(","), controller, hostCard, stAb);
// Add back all cards that are in other player's graveyard, and meet the restrictions without YouOwn/YouCtrl (treat it as in your graveyard)
if (affectedCardsOriginal != null) {
String affectedParam = stAb.getParam("Affected");
affectedParam = affectedParam.replaceAll("[\\.\\+]YouOwn", "");
affectedParam = affectedParam.replaceAll("[\\.\\+]YouCtrl", "");
String[] restrictions = affectedParam.split(",");
for (final Card card : affectedCardsOriginal) {
if (card.isInZone(ZoneType.Graveyard) && card.getController() != controller && card.isValid(restrictions, controller, hostCard, stAb)) {
affectedCards.add(card);
}
}
}
}
affectedCards.removeAll(stAb.getIgnoreEffectCards());

View File

@@ -631,13 +631,12 @@ public class TriggerHandler {
}
public void onPlayerLost(Player p) {
List<Trigger> lost = new ArrayList<>();
for (Trigger t : delayedTriggers) {
// CR 603.2f owner of trigger source lost game || 800.4d trigger controller lost game
if (game.getCardState(t.getHostCard(), null) == null || t.getHostCard().getOwner().equals(p)) {
lost.add(t);
List<Trigger> lost = new ArrayList<>(delayedTriggers);
for (Trigger t : lost) {
// CR 800.4d trigger controller lost game
if (t.getHostCard().getOwner().equals(p)) {
delayedTriggers.remove(t);
}
}
delayedTriggers.removeAll(lost);
}
}

View File

@@ -586,7 +586,7 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
}
if (source.isCopiedSpell() && source.isInZone(ZoneType.Stack)) {
source.ceaseToExist();
source.ceaseToExist(true);
return;
}

View File

@@ -0,0 +1,10 @@
Name:Shaman's Trance
ManaCost:2 R
Types:Instant
A:SP$ Effect | Cost$ 2 R | StaticAbilities$ STCantPlayLand,STCantCastSpell,STTrance | SpellDescription$ Other players can't play lands or cast spells from their graveyards this turn. You may play lands and cast spells from other players' graveyards this turn as though those cards were in your graveyard.
SVar:STCantPlayLand:Mode$ CantPlayLand | ValidCard$ Land | Origin$ Graveyard | Player$ Player.Other | EffectZone$ Command | Description$ Other players can't play lands from their graveyards this turn.
SVar:STCantCastSpell:Mode$ CantBeCast | ValidCard$ Card | Origin$ Graveyard | Caster$ Player.Other | EffectZone$ Command | Description$ Other players cast spells from their graveyards this turn.
SVar:STTrance:Mode$ Continuous | Affected$ You | AddKeyword$ Shaman's Trance | Description$ You may play lands and cast spells from other players' graveyards this turn as though those cards were in your graveyard.
AI:RemoveDeck:All
AI:RemoveDeck:Random
Oracle:Other players can't play lands or cast spells from their graveyards this turn. You may play lands and cast spells from other players' graveyards this turn as though those cards were in your graveyard.

View File

@@ -6,8 +6,9 @@ K:Flying
K:Vigilance
K:Trample
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigTokenFly | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME dies, create a 3/3 colorless Golem artifact creature token with flying, a 3/3 colorless Golem artifact creature token with vigilance, and a 3/3 colorless Golem artifact creature token with trample.
SVar:TrigTokenFly:DB$Token | TokenAmount$ 1 | TokenScript$ c_3_3_a_golem_flying | SubAbility$ DBTokenVig
SVar:TrigTokenFly:DB$Token | TokenAmount$ 1 | TokenScript$ c_3_3_a_golem_flying | ChangeZoneTable$ True | SubAbility$ DBTokenVig
SVar:DBTokenVig:DB$Token | TokenAmount$ 1 | TokenScript$ c_3_3_a_golem_vigilance | SubAbility$ DBTokenTra
SVar:DBTokenTra:DB$Token | TokenAmount$ 1 | TokenScript$ c_3_3_a_golem_trample
SVar:DBTokenTra:DB$Token | TokenAmount$ 1 | TokenScript$ c_3_3_a_golem_trample | SubAbility$ DBResolve
SVar:DBResolve:DB$ ChangeZoneResolve
DeckHas:Ability$Token
Oracle:Flying, vigilance, trample\nWhen Triplicate Titan dies, create a 3/3 colorless Golem artifact creature token with flying, a 3/3 colorless Golem artifact creature token with vigilance, and a 3/3 colorless Golem artifact creature token with trample.

View File

@@ -580,6 +580,7 @@ lblQuestOpponentDecks=Quest-Gegner-Deck
lblRandomColorDecks=Decks - zufällige Farben
lblRandomStandardArchetypeDecks=Decks - zufälliger Standard-Archetyp
lblRandomPioneerArchetypeDecks=Decks - zufälliger Pioneer-Archetyp
lblRandomHistoricArchetypeDecks=Decks - zufälliger Historisch-Archetyp
lblRandomModernArchetypeDecks=Decks - zufälliger Modern-Archetyp
lblRandomLegacyArchetypeDecks=Decks - zufälliger Legacy-Archetyp
lblRandomVintageArchetypeDecks=Decks - zufälliger Vintage-Archetyp
@@ -2674,4 +2675,4 @@ lblWildOpponentNumberError=Anzahl der Wild-Gegner kann nur 0 bis 3 sein
#GauntletWinLose.java
lblGauntletProgress=Spießrutenlauf-Fortschritt
#SpellAbility.java
lblInvalidTargetSpecification=Not all target requirements are met.
lblInvalidTargetSpecification=Nicht alle Zielbedingungen sind erfüllt.

View File

@@ -265,7 +265,10 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
public SpellAbility getAbilityToPlay(final Card hostCard, final List<SpellAbility> abilities,
final ITriggerEvent triggerEvent) {
// make sure another human player can't choose opponents cards just because he might see them
if (triggerEvent != null && !hostCard.isInZone(ZoneType.Battlefield) && !hostCard.getOwner().equals(player) && !hostCard.getController().equals(player) && hostCard.mayPlay(player).size() == 0) {
if (triggerEvent != null && !hostCard.isInZone(ZoneType.Battlefield) && !hostCard.getOwner().equals(player) &&
!hostCard.getController().equals(player) && hostCard.mayPlay(player).size() == 0 &&
// If player cast Shaman's Trance, they can play spells from any Graveyard (if other effects allow it to be cast)
(!player.hasKeyword("Shaman's Trance") || !hostCard.isInZone(ZoneType.Graveyard))) {
return null;
}
spellViewCache = SpellAbilityView.getMap(abilities);
@@ -2838,7 +2841,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
continue;
}
c.getZone().remove(c);
c.ceaseToExist();
c.ceaseToExist(true);
StringBuilder sb = new StringBuilder();
sb.append(p).append(" removes ").append(c).append(" from game due to Dev Cheats.");