From 5fa9f5b50e325346c8e44b041df8c05584a36af9 Mon Sep 17 00:00:00 2001 From: tool4ever Date: Thu, 21 Nov 2024 17:58:13 +0100 Subject: [PATCH 1/6] Fix Kentaro (#6600) --- .../main/java/forge/card/mana/ManaCost.java | 2 +- .../game/ability/effects/CounterEffect.java | 5 +++ .../forge/game/mana/ManaCostBeingPaid.java | 2 +- .../main/java/forge/game/player/Player.java | 43 ++++++++++--------- .../game/replacement/ReplacementHandler.java | 9 ---- .../cardsfolder/a/archon_of_coronation.txt | 2 +- forge-gui/res/cardsfolder/c/complicate.txt | 2 +- forge-gui/res/cardsfolder/m/mystic_remora.txt | 4 +- .../res/cardsfolder/p/paradise_druid.txt | 4 +- .../res/cardsfolder/p/plumb_the_forbidden.txt | 2 +- .../res/cardsfolder/s/simic_basilisk.txt | 2 +- .../res/cardsfolder/s/sloppity_bilepiper.txt | 2 +- 12 files changed, 39 insertions(+), 40 deletions(-) diff --git a/forge-core/src/main/java/forge/card/mana/ManaCost.java b/forge-core/src/main/java/forge/card/mana/ManaCost.java index fdfa28734c2..6773fb8ad75 100644 --- a/forge-core/src/main/java/forge/card/mana/ManaCost.java +++ b/forge-core/src/main/java/forge/card/mana/ManaCost.java @@ -100,7 +100,7 @@ public final class ManaCost implements Comparable, Iterable { return drawn; } - // Replacement effects - final Map repRunParams = AbilityKey.mapFromAffected(this); - repRunParams.put(AbilityKey.Number, n); - if (params != null) { - repRunParams.putAll(params); - } - - if (game.getReplacementHandler().run(ReplacementType.DrawCards, repRunParams) != ReplacementResult.NotReplaced) { - return drawn; - } - // always allow drawing cards before the game actually starts (e.g. Maralen of the Mornsong Avatar) final boolean gameStarted = game.getAge().ordinal() > GameStage.Mulligan.ordinal(); + + if (gameStarted) { + final Map repRunParams = AbilityKey.mapFromAffected(this); + repRunParams.put(AbilityKey.Number, n); + if (params != null) { + repRunParams.putAll(params); + } + if (game.getReplacementHandler().run(ReplacementType.DrawCards, repRunParams) != ReplacementResult.NotReplaced) { + return drawn; + } + } + final Map toReveal = Maps.newHashMap(); for (int i = 0; i < n; i++) { @@ -1249,14 +1250,17 @@ public class Player extends GameEntity implements Comparable { cause = (SpellAbility) cause.getReplacingObject(AbilityKey.Cause); } - // Replacement effects - Map repParams = AbilityKey.mapFromAffected(this); - repParams.put(AbilityKey.Cause, cause); - if (params != null) { - repParams.putAll(params); - } - if (game.getReplacementHandler().run(ReplacementType.Draw, repParams) != ReplacementResult.NotReplaced) { - return drawn; + final boolean gameStarted = game.getAge().ordinal() > GameStage.Mulligan.ordinal(); + + if (gameStarted) { + Map repParams = AbilityKey.mapFromAffected(this); + repParams.put(AbilityKey.Cause, cause); + if (params != null) { + repParams.putAll(params); + } + if (game.getReplacementHandler().run(ReplacementType.Draw, repParams) != ReplacementResult.NotReplaced) { + return drawn; + } } if (!library.isEmpty()) { @@ -1291,7 +1295,6 @@ public class Player extends GameEntity implements Comparable { revealed.get(p).add(c); } - final boolean gameStarted = game.getAge().ordinal() > GameStage.Mulligan.ordinal(); if (gameStarted) { setLastDrawnCard(c); c.setDrawnThisTurn(true); diff --git a/forge-game/src/main/java/forge/game/replacement/ReplacementHandler.java b/forge-game/src/main/java/forge/game/replacement/ReplacementHandler.java index 75262669cfe..0146bf1390d 100644 --- a/forge-game/src/main/java/forge/game/replacement/ReplacementHandler.java +++ b/forge-game/src/main/java/forge/game/replacement/ReplacementHandler.java @@ -71,8 +71,6 @@ public class ReplacementHandler { game = gameState; } - //private final List tmpEffects = new ArrayList(); - public List getReplacementList(final ReplacementType event, final Map runParams, final ReplacementLayer layer) { final CardCollection preList = new CardCollection(); boolean checkAgain = false; @@ -108,13 +106,6 @@ public class ReplacementHandler { } final List possibleReplacers = Lists.newArrayList(); - // Round up Non-static replacement effects ("Until EOT," or - // "The next time you would..." etc) - /*for (final ReplacementEffect replacementEffect : this.tmpEffects) { - if (!replacementEffect.hasRun() && replacementEffect.canReplace(runParams) && replacementEffect.getLayer() == layer) { - possibleReplacers.add(replacementEffect); - } - }*/ // Round up Static replacement effects game.forEachCardInGame(new Visitor() { diff --git a/forge-gui/res/cardsfolder/a/archon_of_coronation.txt b/forge-gui/res/cardsfolder/a/archon_of_coronation.txt index a21b851b094..9e0f62891a7 100644 --- a/forge-gui/res/cardsfolder/a/archon_of_coronation.txt +++ b/forge-gui/res/cardsfolder/a/archon_of_coronation.txt @@ -5,5 +5,5 @@ PT:5/5 K:Flying T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigMonarch | TriggerDescription$ When CARDNAME enters, you become the monarch. SVar:TrigMonarch:DB$ BecomeMonarch | Defined$ You -R:Event$ LifeReduced | ValidPlayer$ You | IsDamage$ True | Monarch$ True | Layer$ CantHappen | Description$ As long as you're the monarch, damage doesn't cause you to lose life. (When a creature deals combat damage to you, its controller still becomes the monarch.) +R:Event$ LifeReduced | ValidPlayer$ You | IsDamage$ True | Monarch$ True | Layer$ CantHappen | ActiveZones$ Battlefield | Description$ As long as you're the monarch, damage doesn't cause you to lose life. (When a creature deals combat damage to you, its controller still becomes the monarch.) Oracle:Flying\nWhen Archon of Coronation enters, you become the monarch.\nAs long as you're the monarch, damage doesn't cause you to lose life. (When a creature deals combat damage to you, its controller still becomes the monarch.) diff --git a/forge-gui/res/cardsfolder/c/complicate.txt b/forge-gui/res/cardsfolder/c/complicate.txt index 6c363acff0e..8e5d6d3bb41 100644 --- a/forge-gui/res/cardsfolder/c/complicate.txt +++ b/forge-gui/res/cardsfolder/c/complicate.txt @@ -4,5 +4,5 @@ Types:Instant K:Cycling:2 U A:SP$ Counter | TargetType$ Spell | TgtPrompt$ Select target spell | ValidTgts$ Card | UnlessCost$ 3 | SpellDescription$ Counter target spell unless its controller pays {3}. T:Mode$ Cycled | ValidCard$ Card.Self | Execute$ TrigExile | TriggerDescription$ When you cycle CARDNAME, you may counter target spell unless its controller pays {1}. -SVar:TrigExile:DB$ Counter | TargetType$ Spell | TgtPrompt$ Select target spell | ValidTgts$ Card | UnlessCost$ 1 +SVar:TrigExile:DB$ Counter | TargetType$ Spell | TgtPrompt$ Select target spell | ValidTgts$ Card | Optional$ True | UnlessCost$ 1 Oracle:Counter target spell unless its controller pays {3}.\nCycling {2}{U} ({2}{U}, Discard this card: Draw a card.)\nWhen you cycle Complicate, you may counter target spell unless its controller pays {1}. diff --git a/forge-gui/res/cardsfolder/m/mystic_remora.txt b/forge-gui/res/cardsfolder/m/mystic_remora.txt index aa994d34814..210d969f7d5 100644 --- a/forge-gui/res/cardsfolder/m/mystic_remora.txt +++ b/forge-gui/res/cardsfolder/m/mystic_remora.txt @@ -2,7 +2,7 @@ Name:Mystic Remora ManaCost:U Types:Enchantment K:Cumulative upkeep:1 -T:Mode$ SpellCast | ValidCard$ Card.nonCreature | ValidActivatingPlayer$ Opponent | TriggerZones$ Battlefield | Execute$ TrigDraw | OptionalDecider$ You | TriggerDescription$ Whenever an opponent casts a noncreature spell, you may draw a card unless that player pays {4}. -SVar:TrigDraw:DB$ Draw | Defined$ You | UnlessCost$ 4 | UnlessPayer$ TriggeredPlayer | NumCards$ 1 +T:Mode$ SpellCast | ValidCard$ Card.nonCreature | ValidActivatingPlayer$ Opponent | TriggerZones$ Battlefield | Execute$ TrigDraw | TriggerDescription$ Whenever an opponent casts a noncreature spell, you may draw a card unless that player pays {4}. +SVar:TrigDraw:DB$ Draw | Defined$ You | UnlessCost$ 4 | UnlessPayer$ TriggeredPlayer | NumCards$ 1 | OptionalDecider$ You AI:RemoveDeck:Random Oracle:Cumulative upkeep {1} (At the beginning of your upkeep, put an age counter on this permanent, then sacrifice it unless you pay its upkeep cost for each age counter on it.)\nWhenever an opponent casts a noncreature spell, you may draw a card unless that player pays {4}. diff --git a/forge-gui/res/cardsfolder/p/paradise_druid.txt b/forge-gui/res/cardsfolder/p/paradise_druid.txt index 08e4976b504..bfffe761022 100644 --- a/forge-gui/res/cardsfolder/p/paradise_druid.txt +++ b/forge-gui/res/cardsfolder/p/paradise_druid.txt @@ -2,6 +2,6 @@ Name:Paradise Druid ManaCost:1 G Types:Creature Elf Druid PT:2/1 -S:Mode$ Continuous | Affected$ Card.Self+untapped | AddKeyword$ Hexproof | Description$ CARDNAME has hexproof as long as it's untapped.(It can't be the target of spells or abilities your opponents control.) +S:Mode$ Continuous | Affected$ Card.Self+untapped | AddKeyword$ Hexproof | Description$ CARDNAME has hexproof as long as it's untapped. (It can't be the target of spells or abilities your opponents control.) A:AB$ Mana | Cost$ T | Produced$ Any | SpellDescription$ Add one mana of any color. -Oracle:Paradise Druid has hexproof as long as it's untapped.(It can't be the target of spells or abilities your opponents control.)\n{T}: Add one mana of any color. +Oracle:Paradise Druid has hexproof as long as it's untapped. (It can't be the target of spells or abilities your opponents control.)\n{T}: Add one mana of any color. diff --git a/forge-gui/res/cardsfolder/p/plumb_the_forbidden.txt b/forge-gui/res/cardsfolder/p/plumb_the_forbidden.txt index bd9acfef136..7efc206584d 100644 --- a/forge-gui/res/cardsfolder/p/plumb_the_forbidden.txt +++ b/forge-gui/res/cardsfolder/p/plumb_the_forbidden.txt @@ -1,7 +1,7 @@ Name:Plumb the Forbidden ManaCost:1 B Types:Instant -T:Mode$ SpellCast | ValidCard$ Card.Self | Execute$ TrigCopy | CheckSVar$ X | TriggerDescription$ As an additional cost to cast this spell, you may sacrifice one or more creatures. When you do, copy this spell for each creature sacrificed this way. +T:Mode$ SpellCast | ValidCard$ Card.Self | Execute$ TrigCopy | CheckSVar$ CastSA>Count$xPaid | TriggerDescription$ As an additional cost to cast this spell, you may sacrifice one or more creatures. When you do, copy this spell for each creature sacrificed this way. SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ X A:SP$ Draw | Cost$ 1 B Sac | SubAbility$ DBLoseLife | CostDesc$ | SpellDescription$ You draw a card and you lose 1 life. SVar:DBLoseLife:DB$ LoseLife | LifeAmount$ 1 diff --git a/forge-gui/res/cardsfolder/s/simic_basilisk.txt b/forge-gui/res/cardsfolder/s/simic_basilisk.txt index 035c0546e58..5e4ea338f5c 100644 --- a/forge-gui/res/cardsfolder/s/simic_basilisk.txt +++ b/forge-gui/res/cardsfolder/s/simic_basilisk.txt @@ -4,7 +4,7 @@ Types:Creature Basilisk Mutant PT:0/0 K:Graft:3 A:AB$ Animate | Cost$ 1 G | ValidTgts$ Creature.counters_GE1_P1P1 | TgtPrompt$ Select target creature with a +1/+1 counter on it | Triggers$ DestroyTrigger | SpellDescription$ Until end of turn, target creature with a +1/+1 counter on it gains "Whenever this creature deals combat damage to a creature, destroy that creature at end of combat." -SVar:DestroyTrigger:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Creature | CombatDamage$ True | TriggerZones$ Battlefield | Execute$ DelTrig | TriggerDescription$ Whenever CARDNAME deals combat damage to a creature, destroy that creature at end of combat. +SVar:DestroyTrigger:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Creature | CombatDamage$ True | TriggerZones$ Battlefield | Execute$ DelTrigSimic | TriggerDescription$ Whenever CARDNAME deals combat damage to a creature, destroy that creature at end of combat. SVar:DelTrigSimic:DB$ DelayedTrigger | Mode$ Phase | Phase$ EndCombat | ValidPlayer$ Player | Execute$ TrigDestroySimic | RememberObjects$ TriggeredTargetLKICopy | TriggerDescription$ Destroy damaged creature at end of combat. SVar:TrigDestroySimic:DB$ Destroy | Defined$ DelayTriggerRememberedLKI SVar:AIGraftPreference:DontMoveCounterIfLethal diff --git a/forge-gui/res/cardsfolder/s/sloppity_bilepiper.txt b/forge-gui/res/cardsfolder/s/sloppity_bilepiper.txt index bb3c708347b..65a3ddb3772 100644 --- a/forge-gui/res/cardsfolder/s/sloppity_bilepiper.txt +++ b/forge-gui/res/cardsfolder/s/sloppity_bilepiper.txt @@ -3,7 +3,7 @@ ManaCost:3 B Types:Creature Demon PT:3/3 A:AB$ Effect | PrecostDesc$ Jolly Gutpipes — | Cost$ 2 T Sac<1/Creature> | StaticAbilities$ GrantCascade | Triggers$ ExileEffect | SpellDescription$ The next creature spell you cast this turn has cascade. (When you cast your next creature spell, exile cards from the top of your library until you exile a nonland card that costs less. You may cast it without paying its mana cost. Put the exiled cards on the bottom of your library in a random order.) -SVar:GrantCascade:Mode$ Continuous | EffectZone$ Command | Affected$ Card.Creature+YouCtrl | AffectedZone$ Stack | Execute$ ExileEff | AddKeyword$ Cascade | Description$ The next noncreature spell you cast this turn has cascade. +SVar:GrantCascade:Mode$ Continuous | EffectZone$ Command | Affected$ Card.Creature+YouCtrl | AffectedZone$ Stack | AddKeyword$ Cascade | Description$ The next noncreature spell you cast this turn has cascade. SVar:ExileEffect:Mode$ SpellCast | EffectZone$ Command | ValidCard$ Card.Creature+YouCtrl | Execute$ RemoveEffect | Static$ True SVar:RemoveEffect:DB$ ChangeZone | Origin$ Command | Destination$ Exile | Defined$ Self DeckHas:Keyword$Cascade & Ability$Sacrifice From 6f59c0d2ce4b2162939d334af7c2309828ce4ac1 Mon Sep 17 00:00:00 2001 From: kevlahnota Date: Fri, 22 Nov 2024 05:58:49 +0800 Subject: [PATCH 2/6] prevent NPE --- forge-gui-mobile/src/forge/card/CardZoom.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/forge-gui-mobile/src/forge/card/CardZoom.java b/forge-gui-mobile/src/forge/card/CardZoom.java index 7060e870273..2e9155c8651 100644 --- a/forge-gui-mobile/src/forge/card/CardZoom.java +++ b/forge-gui-mobile/src/forge/card/CardZoom.java @@ -377,9 +377,11 @@ public class CardZoom extends FOverlay { float x = (w - cardWidth) / 2; y = (h - cardHeight) / 2; if (zoomMode) { - CardImageRenderer.drawZoom(g, currentCard, gameView, showBackSide? showBackSide : showAltState, x, y, cardWidth, cardHeight, getWidth(), getHeight(), true); + if (currentCard != null) + CardImageRenderer.drawZoom(g, currentCard, gameView, showBackSide? showBackSide : showAltState, x, y, cardWidth, cardHeight, getWidth(), getHeight(), true); } else { - CardImageRenderer.drawDetails(g, currentCard, gameView, showBackSide ? showBackSide : showAltState, x, y, cardWidth, cardHeight); + if (currentCard != null) + CardImageRenderer.drawDetails(g, currentCard, gameView, showBackSide ? showBackSide : showAltState, x, y, cardWidth, cardHeight); } if (!showMerged) { From 29ce2e01fd9680372078353a20976f86d3519bdc Mon Sep 17 00:00:00 2001 From: kevlahnota Date: Fri, 22 Nov 2024 06:04:25 +0800 Subject: [PATCH 3/6] Update ImageView.java --- .../src/main/java/forge/itemmanager/views/ImageView.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/forge-gui-desktop/src/main/java/forge/itemmanager/views/ImageView.java b/forge-gui-desktop/src/main/java/forge/itemmanager/views/ImageView.java index e01969bbeef..0136367ac69 100644 --- a/forge-gui-desktop/src/main/java/forge/itemmanager/views/ImageView.java +++ b/forge-gui-desktop/src/main/java/forge/itemmanager/views/ImageView.java @@ -591,10 +591,12 @@ public class ImageView extends ItemView { Map, Pile> piles = new TreeMap<>(); for (ItemInfo itemInfo : group.items) { Comparable key = groupPileBy.fnSort.apply(itemInfo); - if (!piles.containsKey(key)) { + if (key != null && !piles.containsKey(key)) { piles.put(key, new Pile()); } - piles.get(key).items.add(itemInfo); + Pile p = key == null ? null : piles.getOrDefault(key, null); + if (p != null) + p.items.add(itemInfo); } group.piles.clear(); group.piles.addAll(piles.values()); From 2bf67e931e897bd780b028b3227f58244ddaf960 Mon Sep 17 00:00:00 2001 From: Chris H Date: Thu, 21 Nov 2024 22:15:51 -0500 Subject: [PATCH 4/6] Update remove-stale-branches.yml --- .github/workflows/remove-stale-branches.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/remove-stale-branches.yml b/.github/workflows/remove-stale-branches.yml index 8f06accdb9d..564c709f28a 100644 --- a/.github/workflows/remove-stale-branches.yml +++ b/.github/workflows/remove-stale-branches.yml @@ -1,4 +1,7 @@ +name: Remove stale branches + on: + workflow_dispatch: schedule: - cron: "0 0 * * *" # Everday at midnight @@ -10,3 +13,4 @@ jobs: - uses: fpicalausa/remove-stale-branches@v1.6.0 with: dry-run: true # Check out the console output before setting this to false + ignore-unknown-authors: true From 4436a83cc558bb83c14d4b39b6ce57aca2aba098 Mon Sep 17 00:00:00 2001 From: Chris H Date: Thu, 21 Nov 2024 22:20:21 -0500 Subject: [PATCH 5/6] Update remove-stale-branches.yml --- .github/workflows/remove-stale-branches.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/remove-stale-branches.yml b/.github/workflows/remove-stale-branches.yml index 564c709f28a..78933088d37 100644 --- a/.github/workflows/remove-stale-branches.yml +++ b/.github/workflows/remove-stale-branches.yml @@ -14,3 +14,4 @@ jobs: with: dry-run: true # Check out the console output before setting this to false ignore-unknown-authors: true + default-recipient: tehdiplomat From 03b87003ef6bf8733f33db368ba1ee1e693af89f Mon Sep 17 00:00:00 2001 From: Chris H Date: Thu, 21 Nov 2024 22:22:32 -0500 Subject: [PATCH 6/6] Update remove-stale-branches.yml --- .github/workflows/remove-stale-branches.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/remove-stale-branches.yml b/.github/workflows/remove-stale-branches.yml index 78933088d37..40a68cf2307 100644 --- a/.github/workflows/remove-stale-branches.yml +++ b/.github/workflows/remove-stale-branches.yml @@ -12,6 +12,6 @@ jobs: steps: - uses: fpicalausa/remove-stale-branches@v1.6.0 with: - dry-run: true # Check out the console output before setting this to false + dry-run: false # Check out the console output before setting this to false ignore-unknown-authors: true default-recipient: tehdiplomat