mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 18:58:00 +00:00
Merge remote-tracking branch 'remotes/core/master'
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
10
forge-gui/res/cardsfolder/s/shamans_trance.txt
Normal file
10
forge-gui/res/cardsfolder/s/shamans_trance.txt
Normal 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.
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.");
|
||||
|
||||
Reference in New Issue
Block a user