Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -897,4 +897,94 @@ public void testPithingNeedlePreventsAbilitiesFromBeingChosen() {
game.getAction().checkStateEffects(true);
AssertJUnit.assertNull(picker.chooseSpellAbilityToPlay(null));
}

@Test
public void testChampionsOfTyrChosenFromMultipleCardsInHand() {
Game game = initAndCreateGame();
Player p = game.getPlayers().get(1);

addCard("Plains", p);
addCard("Plains", p);
addCard("Mountain", p);
addCard("Mountain", p);
Card champions = addCardToZone("Champions of Tyr", p, ZoneType.Hand);
addCardToZone("Grizzly Bears", p, ZoneType.Hand);

game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
game.getAction().checkStateEffects(true);

SpellAbilityPicker picker = new SpellAbilityPicker(game, p);
SpellAbility sa = picker.chooseSpellAbilityToPlay(null);
AssertJUnit.assertNotNull(sa);
AssertJUnit.assertEquals(champions, sa.getHostCard());
}

@Test
public void testChampionsOfTyrNotChosenWhenInsufficientMana() {
Game game = initAndCreateGame();
Player p = game.getPlayers().get(1);

addCard("Plains", p);
addCard("Plains", p);
addCard("Mountain", p);
addCardToZone("Champions of Tyr", p, ZoneType.Hand);

game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
game.getAction().checkStateEffects(true);

SpellAbilityPicker picker = new SpellAbilityPicker(game, p);
SpellAbility sa = picker.chooseSpellAbilityToPlay(null);
AssertJUnit.assertNull(sa);
}

@Test
public void testChampionsOfTyrDeprioritizedWhenLethalIsAvailable() {
Game game = initAndCreateGame();
Player p = game.getPlayers().get(1);
Player opponent = game.getPlayers().get(0);
p.setTeam(0);
opponent.setTeam(1);

addCard("Plains", p);
addCard("Plains", p);
addCard("Mountain", p);
addCard("Mountain", p);
addCardToZone("Champions of Tyr", p, ZoneType.Hand);
Card shock = addCardToZone("Shock", p, ZoneType.Hand);
opponent.setLife(2, null);

game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
game.getAction().checkStateEffects(true);

SpellAbilityPicker picker = new SpellAbilityPicker(game, p);
SpellAbility sa = picker.chooseSpellAbilityToPlay(null);
AssertJUnit.assertNotNull(sa);
AssertJUnit.assertEquals(shock, sa.getHostCard());
AssertJUnit.assertEquals(opponent, sa.getTargets().getFirstTargetedPlayer());
}

@Test
public void testChampionsOfTyrDeprioritizedAgainstImmediateThreat() {
Game game = initAndCreateGame();
Player p = game.getPlayers().get(1);
Player opponent = game.getPlayers().get(0);

addCard("Plains", p);
addCard("Plains", p);
addCard("Swamp", p);
addCard("Mountain", p);
addCardToZone("Champions of Tyr", p, ZoneType.Hand);
Card doomBlade = addCardToZone("Doom Blade", p, ZoneType.Hand);
Card dragon = addCard("Shivan Dragon", opponent);
p.setLife(5, null);

game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
game.getAction().checkStateEffects(true);

SpellAbilityPicker picker = new SpellAbilityPicker(game, p);
SpellAbility sa = picker.chooseSpellAbilityToPlay(null);
AssertJUnit.assertNotNull(sa);
AssertJUnit.assertEquals(doomBlade, sa.getHostCard());
AssertJUnit.assertEquals(dragon, sa.getTargetCard());
}
}
6 changes: 3 additions & 3 deletions forge-gui/res/cardsfolder/c/champions_of_tyr.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ PT:4/3
K:Flying
K:Double team
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ DBBoon | TriggerDescription$ When CARDNAME enters, you get a boon with "When you cast your next creature spell, that creature enters with your choice of a +1/+1 counter, a flying counter, or a lifelink counter on it."
SVar:DBBoon:DB$ Effect | Boon$ True | Duration$ Permanent | Triggers$ SpellCast
SVar:DBBoon:DB$ Effect | Boon$ True | Duration$ Permanent | Triggers$ SpellCast | AILogic$ Always
SVar:SpellCast:Mode$ SpellCast | ValidCard$ Creature | ValidActivatingPlayer$ You | TriggerZones$ Command | Execute$ ReplEffAddCounter | TriggerDescription$ When you cast your next creature spell, that creature enters with an additional +1/+1 counter, flying counter, and lifelink counter on it.
SVar:ReplEffAddCounter:DB$ Effect | ReplacementEffects$ ETBAddCounter | RememberObjects$ TriggeredCard
SVar:ReplEffAddCounter:DB$ Effect | ReplacementEffects$ ETBAddCounter | RememberObjects$ TriggeredCard | AILogic$ Always
SVar:ETBAddCounter:Event$ Moved | Origin$ Stack | Destination$ Battlefield | ValidCard$ Card.IsRemembered | ReplacementResult$ Updated | ReplaceWith$ ETBAddExtraCounter
SVar:ETBAddExtraCounter:DB$ PutCounter | ETB$ True | Defined$ ReplacedCard | CounterType$ P1P1,Flying,Lifelink | CounterNum$ 1 | SubAbility$ DBRemoveSelf
SVar:ETBAddExtraCounter:DB$ PutCounter | ETB$ True | Defined$ ReplacedCard | CounterType$ P1P1,Flying,Lifelink | CounterNum$ 1 | AILogic$ Always | SubAbility$ DBRemoveSelf
SVar:DBRemoveSelf:DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile
DeckHas:Ability$LifeGain|Counters & Keyword$Lifelink|Flying
Oracle:Flying\nDouble team\nWhen Champions of Tyr enters, you get a boon with "When you cast your next creature spell, that creature enters with your choice of a +1/+1 counter, a flying counter, or a lifelink counter on it."
16 changes: 14 additions & 2 deletions forge-gui/src/main/java/forge/error/ExceptionHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,13 @@ public static void unregisterErrorHandling() throws IOException {
/** {@inheritDoc} */
@Override
public final void uncaughtException(final Thread t, final Throwable ex) {
BugReporter.reportException(ex);
try {
BugReporter.reportException(ex);
} catch (final Throwable handlerFailure) {
System.err.println("Uncaught exception handler failed while reporting the original exception:");
ex.printStackTrace();
handlerFailure.printStackTrace();
}
}

/**
Expand All @@ -110,6 +116,12 @@ public final void uncaughtException(final Thread t, final Throwable ex) {
* a {@link java.lang.Throwable} object.
*/
public final void handle(final Throwable ex) {
BugReporter.reportException(ex);
try {
BugReporter.reportException(ex);
} catch (final Throwable handlerFailure) {
System.err.println("AWT exception handler failed while reporting the original exception:");
ex.printStackTrace();
handlerFailure.printStackTrace();
}
}
}