mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 20:58:03 +00:00
King of the Oathbreakers should trigger for Changeling (Discord post) (#6453)
* Fix NPE with Street Spasm
This commit is contained in:
@@ -249,13 +249,6 @@ public class GameAction {
|
||||
|
||||
copied = new CardCopyService(c).copyCard(false);
|
||||
|
||||
// CR 707.12 casting of a card copy
|
||||
if (zoneTo.is(ZoneType.Stack) && c.isRealToken()) {
|
||||
copied.setCopiedPermanent(c.getCopiedPermanent());
|
||||
//TODO: Feels like this should fit here and seems to work but it'll take a fair bit more testing to be sure.
|
||||
//copied.setGamePieceType(GamePieceType.COPIED_SPELL);
|
||||
}
|
||||
|
||||
copied.setGameTimestamp(c.getGameTimestamp());
|
||||
|
||||
if (zoneTo.is(ZoneType.Stack)) {
|
||||
@@ -267,6 +260,13 @@ public class GameAction {
|
||||
copied.setExiledBy(c.getExiledBy());
|
||||
copied.setDrawnThisTurn(c.getDrawnThisTurn());
|
||||
|
||||
// CR 707.12 casting of a card copy
|
||||
if (c.isRealToken()) {
|
||||
copied.setCopiedPermanent(c.getCopiedPermanent());
|
||||
//TODO: Feels like this should fit here and seems to work but it'll take a fair bit more testing to be sure.
|
||||
//copied.setGamePieceType(GamePieceType.COPIED_SPELL);
|
||||
}
|
||||
|
||||
if (c.isTransformed()) {
|
||||
copied.incrementTransformedTimestamp();
|
||||
}
|
||||
@@ -277,6 +277,7 @@ public class GameAction {
|
||||
|
||||
// CR 112.2 A spell’s controller is, by default, the player who put it on the stack.
|
||||
copied.setController(cause.getActivatingPlayer(), 0);
|
||||
|
||||
KeywordInterface kw = cause.getKeyword();
|
||||
if (kw != null) {
|
||||
copied.addKeywordForStaticAbility(kw);
|
||||
@@ -290,25 +291,24 @@ public class GameAction {
|
||||
copied.setBackSide(false);
|
||||
}
|
||||
|
||||
copied.setUnearthed(c.isUnearthed());
|
||||
|
||||
// need to copy counters when card enters another zone than hand or library
|
||||
if (lastKnownInfo.hasKeyword("Counters remain on CARDNAME as it moves to any zone other than a player's hand or library.") &&
|
||||
!(zoneTo.is(ZoneType.Hand) || zoneTo.is(ZoneType.Library))) {
|
||||
copied.setCounters(Maps.newHashMap(lastKnownInfo.getCounters()));
|
||||
}
|
||||
|
||||
// perpetual stuff
|
||||
if (c.hasIntensity()) {
|
||||
copied.setIntensity(c.getIntensity(false));
|
||||
}
|
||||
if (c.isSpecialized()) {
|
||||
copied.setState(c.getCurrentStateName(), false);
|
||||
}
|
||||
if (c.hasPerpetual()) {
|
||||
copied.setPerpetual(c);
|
||||
}
|
||||
}
|
||||
|
||||
// perpetual stuff
|
||||
if (c.hasIntensity()) {
|
||||
copied.setIntensity(c.getIntensity(false));
|
||||
}
|
||||
if (c.isSpecialized()) {
|
||||
copied.setState(c.getCurrentStateName(), false);
|
||||
}
|
||||
if (c.hasPerpetual()) {
|
||||
copied.setPerpetual(c);
|
||||
}
|
||||
// ensure that any leftover keyword/type changes are cleared in the state view
|
||||
copied.updateStateForView();
|
||||
|
||||
@@ -780,8 +780,6 @@ public class GameAction {
|
||||
final Zone zoneFrom = game.getZoneOf(c);
|
||||
// String prevName = prev != null ? prev.getZoneName() : "";
|
||||
|
||||
// Card lastKnownInfo = c;
|
||||
|
||||
// Handle the case that one component of a merged permanent got take to the subgame
|
||||
if (zoneTo.is(ZoneType.Subgame) && (c.hasMergedCard() || c.isMerged())) {
|
||||
c.moveMergedToSubgame(cause);
|
||||
@@ -913,7 +911,7 @@ public class GameAction {
|
||||
}
|
||||
return changeZone(game.getZoneOf(c), deck, c, deckPosition, cause, params);
|
||||
}
|
||||
|
||||
|
||||
public final Card moveToJunkyard(Card c, SpellAbility cause, Map<AbilityKey, Object> params) {
|
||||
final PlayerZone junkyard = c.getOwner().getZone(ZoneType.Junkyard);
|
||||
return moveTo(junkyard, c, cause, params);
|
||||
@@ -931,7 +929,6 @@ public class GameAction {
|
||||
final PlayerZone removed = c.getOwner().getZone(ZoneType.Exile);
|
||||
final Card copied = moveTo(removed, c, cause, params);
|
||||
|
||||
// Run triggers
|
||||
final Map<AbilityKey, Object> runParams = AbilityKey.mapFromCard(c);
|
||||
runParams.put(AbilityKey.Cause, cause);
|
||||
if (origin != null) { // is generally null when adding via dev mode
|
||||
@@ -1264,10 +1261,9 @@ public class GameAction {
|
||||
AbilityKey.addCardZoneTableParams(mapParams, table);
|
||||
|
||||
for (final Player p : game.getPlayers()) {
|
||||
for (final ZoneType zt : ZoneType.values()) {
|
||||
if (zt == ZoneType.Command)
|
||||
p.checkKeywordCard();
|
||||
p.checkKeywordCard();
|
||||
|
||||
for (final ZoneType zt : ZoneType.values()) {
|
||||
if (zt == ZoneType.Battlefield) {
|
||||
continue;
|
||||
}
|
||||
@@ -1275,7 +1271,9 @@ public class GameAction {
|
||||
checkAgain |= stateBasedAction704_5d(c);
|
||||
// Dungeon Card won't affect other cards, so don't need to set checkAgain
|
||||
stateBasedAction_Dungeon(c);
|
||||
stateBasedAction_Scheme(c);
|
||||
if (zt == ZoneType.Command) {
|
||||
stateBasedAction_Scheme(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1557,7 +1555,7 @@ public class GameAction {
|
||||
return;
|
||||
}
|
||||
if (!game.getStack().hasSourceOnStack(c, null)) {
|
||||
moveTo(ZoneType.SchemeDeck, c, null, AbilityKey.newMap());
|
||||
moveTo(ZoneType.SchemeDeck, c, -1, null, AbilityKey.newMap());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1676,7 +1674,6 @@ public class GameAction {
|
||||
FCollectionView<Player> allPlayers = game.getPlayers();
|
||||
for (Player p : allPlayers) {
|
||||
if (p.checkLoseCondition()) { // this will set appropriate outcomes
|
||||
// Run triggers
|
||||
if (losers == null) {
|
||||
losers = Lists.newArrayListWithCapacity(3);
|
||||
}
|
||||
@@ -1898,7 +1895,6 @@ public class GameAction {
|
||||
}
|
||||
}
|
||||
for (Map.Entry<Player, Collection<Card>> e : lki.asMap().entrySet()) {
|
||||
// Run triggers
|
||||
final Map<AbilityKey, Object> runParams = AbilityKey.mapFromPlayer(e.getKey());
|
||||
runParams.put(AbilityKey.Cards, new CardCollection(e.getValue()));
|
||||
runParams.put(AbilityKey.Cause, source);
|
||||
|
||||
@@ -367,7 +367,6 @@ public class DigEffect extends SpellAbilityEffect {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (Card c : movedCards) {
|
||||
Map<AbilityKey, Object> moveParams = AbilityKey.newMap();
|
||||
AbilityKey.addCardZoneTableParams(moveParams, zoneMovements);
|
||||
|
||||
@@ -259,8 +259,10 @@ public class Untap extends Phase {
|
||||
}
|
||||
|
||||
public static void doPhasing(final Player turn) {
|
||||
Game game = turn.getGame();
|
||||
|
||||
// Needs to include phased out cards
|
||||
final List<Card> list = CardLists.filter(turn.getGame().getCardsIncludePhasingIn(ZoneType.Battlefield),
|
||||
final List<Card> list = CardLists.filter(game.getCardsIncludePhasingIn(ZoneType.Battlefield),
|
||||
c -> (c.isPhasedOut(turn) && c.isDirectlyPhasedOut())
|
||||
|| (c.hasKeyword(Keyword.PHASING) && c.getController().equals(turn))
|
||||
);
|
||||
@@ -299,11 +301,13 @@ public class Untap extends Phase {
|
||||
if (!phasedOut.isEmpty()) {
|
||||
final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
|
||||
runParams.put(AbilityKey.Cards, phasedOut);
|
||||
turn.getGame().getTriggerHandler().runTrigger(TriggerType.PhaseOutAll, runParams, false);
|
||||
game.getTriggerHandler().runTrigger(TriggerType.PhaseOutAll, runParams, false);
|
||||
}
|
||||
if (!toPhase.isEmpty()) {
|
||||
// refresh statics for phased in permanents (e.g. so King of the Oathbreakers sees Changeling)
|
||||
game.getAction().checkStaticAbilities();
|
||||
// collect now before some zone change during Untap resets triggers
|
||||
turn.getGame().getTriggerHandler().collectTriggerForWaiting();
|
||||
game.getTriggerHandler().collectTriggerForWaiting();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -694,8 +694,7 @@ public class ReplacementHandler {
|
||||
|
||||
// Determine if need to divide shield among affected entity and
|
||||
// determine if the prevent next N damage shield is large enough to replace all damage
|
||||
Map<String, String> mapParams = chosenRE.getMapParams();
|
||||
if ((mapParams.containsKey("PreventionEffect") && mapParams.get("PreventionEffect").equals("NextN"))
|
||||
if ((chosenRE.hasParam("PreventionEffect") && chosenRE.getParam("PreventionEffect").equals("NextN"))
|
||||
|| apiType == ApiType.ReplaceSplitDamage) {
|
||||
if (apiType == ApiType.ReplaceDamage) {
|
||||
shieldAmount = AbilityUtils.calculateAmount(effectSA.getHostCard(), effectSA.getParamOrDefault("Amount", "1"), effectSA);
|
||||
|
||||
@@ -625,9 +625,11 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
|
||||
}
|
||||
|
||||
game.fireEvent(new GameEventSpellResolved(sa, thisHasFizzled));
|
||||
finishResolving(sa, thisHasFizzled);
|
||||
|
||||
game.getAction().checkStaticAbilities();
|
||||
|
||||
finishResolving(sa, thisHasFizzled);
|
||||
|
||||
game.copyLastState();
|
||||
if (isEmpty() && !hasSimultaneousStackEntries()) {
|
||||
// assuming that if the stack is empty, no reason to hold on to old LKI data (everything is a new object)
|
||||
|
||||
Reference in New Issue
Block a user