Skip to content

Commit

Permalink
Merge pull request #6386 from dracontes/rb-sld-2-marvel
Browse files Browse the repository at this point in the history
SLD: Marvel x MTG Superdrop
  • Loading branch information
paulsnoops authored Oct 20, 2024
2 parents 98c0959 + 0186759 commit 5a3f2ed
Show file tree
Hide file tree
Showing 13 changed files with 102 additions and 38 deletions.
6 changes: 3 additions & 3 deletions forge-ai/src/main/java/forge/ai/AiCostDecision.java
Original file line number Diff line number Diff line change
Expand Up @@ -838,12 +838,12 @@ public PaymentDecision visit(CostPayShards cost) {

@Override
public PaymentDecision visit(CostUnattach cost) {
final Card cardToUnattach = cost.findCardToUnattach(source, player, ability);
if (cardToUnattach == null) {
final CardCollection cardToUnattach = cost.findCardToUnattach(source, player, ability);
if (cardToUnattach.isEmpty()) {
// We really shouldn't be able to get here if there's nothing to unattach
return null;
}
return PaymentDecision.card(cardToUnattach);
return PaymentDecision.card(cardToUnattach.getFirst());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,12 +177,18 @@ public boolean replaceCounterEffect(final Game game, final SpellAbility cause, f
value = Math.min(value, Integer.parseInt(cause.getParam("MaxFromEffect")) - gm.getKey().getCounters(ec.getKey()));
}
gm.getKey().addCounterInternal(ec.getKey(), value, e.getKey().orNull(), true, result, runParams);
if (remember && ec.getValue() >= 1) {
if (remember && ec.getValue() > 0) {
cause.getHostCard().addRemembered(gm.getKey());
}
}
}
}

int totalAdded = totalValues();
if (totalAdded > 0 && cause != null && cause.hasParam("RememberAmount")) {
cause.getHostCard().addRemembered(totalAdded);
}

result.triggerCountersPutAll(game);
return !result.isEmpty();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,6 @@ public void resolve(SpellAbility sa) {
}

table.replaceCounterEffect(game, sa, true);

//for cards like Agitator Ant/Spectacular Showdown that care if counters were actually put on,
// instead use "RememberPut" – this checks after replacement
if (sa.hasParam("RememberCards")) { // remembers whether counters actually placed or not
host.addRemembered(table.columnKeySet());
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -591,18 +591,14 @@ public void resolve(SpellAbility sa) {
final Card card = sa.getHostCard();
final Game game = card.getGame();
final Player activator = sa.getActivatingPlayer();

String amount = sa.getParamOrDefault("CounterNum", "1");
boolean rememberAmount = sa.hasParam("RememberAmount");
final String amount = sa.getParamOrDefault("CounterNum", "1");
final int counterAmount = AbilityUtils.calculateAmount(card, amount, sa);

Player placer = activator;
if (sa.hasParam("Placer")) {
final String pstr = sa.getParam("Placer");
placer = AbilityUtils.getDefinedPlayers(card, pstr, sa).get(0);
placer = AbilityUtils.getDefinedPlayers(card, sa.getParam("Placer"), sa).get(0);
}

int counterAmount = AbilityUtils.calculateAmount(card, amount, sa);

GameEntityCounterTable table = new GameEntityCounterTable();

if (sa.hasParam("TriggeredCounterMap")) {
Expand Down Expand Up @@ -648,12 +644,6 @@ public void resolve(SpellAbility sa) {

table.replaceCounterEffect(game, sa, true);

int totalAdded = table.totalValues();
if (totalAdded > 0 && rememberAmount) {
// TODO use SpellAbility Remember later
card.addRemembered(totalAdded);
}

if (sa.hasParam("RemovePhase")) {
for (Map.Entry<GameEntity, Map<CounterType, Integer>> e : table.row(Optional.of(placer)).entrySet()) {
for (Map.Entry<CounterType, Integer> ce : e.getValue().entrySet()) {
Expand Down
21 changes: 10 additions & 11 deletions forge-game/src/main/java/forge/game/cost/CostUnattach.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@
*/
package forge.game.cost;

import java.util.List;

import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardLists;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
Expand Down Expand Up @@ -70,27 +69,27 @@ public final String toString() {
*/
@Override
public final boolean canPay(final SpellAbility ability, final Player payer, final boolean effect) {
return findCardToUnattach(ability.getHostCard(), payer, ability) != null;
return !findCardToUnattach(ability.getHostCard(), payer, ability).isEmpty();
}

public Card findCardToUnattach(final Card source, Player activator, SpellAbility ability) {
public CardCollection findCardToUnattach(final Card source, Player activator, SpellAbility ability) {
CardCollection attachees = new CardCollection();
if (payCostFromSource()) {
if (source.isEquipping()) {
return source;
attachees.add(source);
}
} else if (getType().equals("OriginalHost")) {
Card originalEquipment = ability.getOriginalHost();
if (originalEquipment.isEquipping()) {
return originalEquipment;
attachees.add(originalEquipment);
}
} else {
List<Card> attachees = CardLists.getValidCards(source.getEquippedBy(), this.getType(), activator, source, ability);
if (attachees.size() > 0) {
// Just pick the first one, although maybe give a dialog
return attachees.get(0);
attachees.addAll(source.getEquippedBy());
if (!getType().contains("X") || ability.getXManaCostPaid() != null) {
attachees = CardLists.getValidCards(attachees, this.getType(), activator, source, ability);
}
}
return null;
return attachees;
}

/* (non-Javadoc)
Expand Down
2 changes: 1 addition & 1 deletion forge-gui/res/cardsfolder/c/cyclopean_tomb.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Name:Cyclopean Tomb
ManaCost:4
Types:Artifact
A:AB$ PutCounter | Cost$ 2 T | ValidTgts$ Land.nonSwamp | TgtPrompt$ Select target non-Swamp land | RememberCards$ True | CounterType$ MIRE | CounterNum$ 1 | ActivationPhases$ Upkeep | SubAbility$ DBEffect | SpellDescription$ Put a mire counter on target non-Swamp land. That land is a Swamp for as long as it has a mire counter on it. Activate only during your upkeep.
A:AB$ PutCounter | Cost$ 2 T | ValidTgts$ Land.nonSwamp | TgtPrompt$ Select target non-Swamp land | RememberPut$ True | CounterType$ MIRE | CounterNum$ 1 | ActivationPhases$ Upkeep | SubAbility$ DBEffect | SpellDescription$ Put a mire counter on target non-Swamp land. That land is a Swamp for as long as it has a mire counter on it. Activate only during your upkeep.
SVar:DBEffect:DB$ Effect | RememberObjects$ Targeted | StaticAbilities$ TombStatic | ForgetOnMoved$ Battlefield | ForgetCounter$ MIRE | Duration$ Permanent
SVar:TombStatic:Mode$ Continuous | EffectZone$ Command | Affected$ Card.IsRemembered | AddType$ Swamp | RemoveLandTypes$ True | Description$ That land is a Swamp for as long as it has a mire counter on it.
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigEffect | TriggerDescription$ When CARDNAME is put into a graveyard from the battlefield, at the beginning of each of your upkeeps for the rest of the game, remove all mire counters from a land that a mire counter was put onto with CARDNAME but that a mire counter has not been removed from with CARDNAME.
Expand Down
14 changes: 14 additions & 0 deletions forge-gui/res/cardsfolder/upcoming/black_panther_wakandan_king.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Name:Black Panther, Wakandan King
ManaCost:G W
Types:Legendary Creature Human Noble Hero
PT:2/2
K:First Strike
T:Mode$ ChangesZone | ValidCard$ Card.Self,Creature.YouCtrl+Other | Origin$ Any | Destination$ Battlefield | Execute$ TrigPutCounter | TriggerZones$ Battlefield | TriggerDescription$ Survey the Realm — Whenever NICKNAME or another creature you control enters, put a +1/+1 counter on target land you control.
SVar:TrigPutCounter:DB$ PutCounter | CounterNum$ 1 | CounterType$ P1P1 | ValidTgts$ Land.YouCtrl | TgtPrompt$ Select target land you control
A:AB$ Pump | Cost$ 3 | PrecostDesc$ Mine Vibranium — | ValidTgts$ Land.YouCtrl | TgtPrompt$ Select target land you control | SubAbility$ DBMove | StackDescription$ SpellDescription | SpellDescription$ Move all +1/+1 counters from target land you control onto target creature. If one or more +1/+1 counters are moved this way, you gain that much life and draw a card.
SVar:DBMove:DB$ MoveCounter | Source$ ParentTarget | ValidTgts$ Creature | TgtPrompt$ Select target creature | CounterType$ P1P1 | CounterNum$ All | RememberAmount$ True | SubAbility$ DBGainLife | StackDescription$ None
SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ X | ConditionCheckSVar$ X | ConditionSVarCompare$ GE1 | SubAbility$ DBDraw | StackDescription$ None
SVar:DBDraw:DB$ Draw | ConditionCheckSVar$ X | ConditionSVarCompare$ GE1 | SubAbility$ DBCleanup | StackDescription$ None
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:X:Count$RememberedNumber
Oracle:First strike\nSurvey the Realm — Whenever Black Panther or another creature you control enters, put a +1/+1 counter on target land you control.\nMine Vibranium — {3}: Move all +1/+1 counters from target land you control onto target creature. If one or more +1/+1 counters are moved this way, you gain that much life and draw a card.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Name:Captain America, First Avenger
ManaCost:R W U
Types:Legendary Creature Human Soldier Hero
PT:4/4
A:AB$ DealDamage | Cost$ 3 Unattach<Equipment.Attached+cmcEQX/an Equipment attached to NICKNAME> | Announce$ X | PrecostDesc$ Throw . . . — | ValidTgts$ Any | TgtPrompt$ Select any target to distribute damage to | NumDmg$ X | TargetMin$ 1 | TargetMax$ 3 | DividedAsYouChoose$ X | SpellDescription$ He deals damage equal to that Equipment's mana value divided as you choose among one, two, or three targets.
SVar:X:Count$xPaid
T:Mode$ Phase | Phase$ BeginCombat | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ DBAttach | TriggerDescription$ . . . Catch — At the beginning of combat on your turn, attach up one target Equipment you control to NICKNAME.
SVar:DBAttach:DB$ Attach | ValidTgts$ Equipment.YouCtrl | TargetMin$ 0 | TargetMax$ 1 | TgtPrompt$ Select up to one target Equipment you control | Object$ Targeted | Defined$ Self
Oracle:Throw . . . — {3}, Unattach an Equipment from Captain America: He deals damage equal to that Equipment's mana value divided as you choose among one, two, or three targets.\n. . . Catch — At the beginning of combat on your turn, attach up one target Equipment you control to Captain America.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Name:Iron Man, Titan of Innovation
ManaCost:3 U R
Types:Legendary Artifact Creature Human Hero
PT:4/4
K:Flying
K:Haste
T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ Genius Industrialist — Whenever NICKNAME attacks, create a Treasure token, then you may sacrifice a noncreature artifact. If you do, search your library for an artifact card with mana value equal to 1 plus the sacrificed artifact's mana value, put it onto the battlefield tapped, then shuffle.
SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ c_a_treasure_sac | TokenOwner$ You | SubAbility$ DBSacrifice
SVar:DBSacrifice:DB$ Sacrifice | SacValid$ Artifact.nonCreature | SacMessage$ noncreature artifact | Optional$ True | RememberSacrificed$ True | SubAbility$ DBChangeZone
SVar:DBChangeZone:DB$ ChangeZone | ConditionDefined$ Remembered | ConditionPresent$ Card | Origin$ Library | Destination$ Battlefield | ChangeType$ Artifact.cmcEQX | ChangeTypeDesc$ artifact card with mana value equal to 1 plus the sacrificed artifact's mana value | ChangeNum$ 1 | Tapped$ True | AILogic$ SacAndUpgrade | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:X:Remembered$CardManaCost/Plus.1
SVar:AIPreference:SacCost$Artifact
DeckNeeds:Type$Artifact
Oracle:Flying, haste\nGenius Industrialist — Whenever Iron Man attacks, create a Treasure token, then you may sacrifice a noncreature artifact. If you do, search your library for an artifact card with mana value equal to 1 plus the sacrificed artifact's mana value, put it onto the battlefield tapped, then shuffle.
12 changes: 12 additions & 0 deletions forge-gui/res/cardsfolder/upcoming/storm_force_of_nature.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Name:Storm, Force of Nature
ManaCost:1 G U R
Types:Legendary Creature Mutant Hero
PT:3/4
K:Flying
K:Vigilance
T:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | Execute$ TrigEffect | CombatDamage$ True | TriggerDescription$ Ceaseless Tempest — Whenever NICKNAME deals combat damage to a player, the next instant or sorcery spell you cast this turn has storm. (When you cast it, copy it for each spell cast before it this turn. You may choose new targets for the copies.)
SVar:TrigEffect:DB$ Effect | StaticAbilities$ GrantStorm | Triggers$ ExileEffect
SVar:GrantStorm:Mode$ Continuous | EffectZone$ Command | Affected$ Instant.YouCtrl,Sorcery.YouCtrl | AffectedZone$ Stack | AddKeyword$ Storm | Description$ The next instant or sorcery spell you cast this turn has storm. (When you cast it, copy it for each spell cast before it this turn. You may choose new targets for the copies.)
SVar:ExileEffect:Mode$ SpellCast | EffectZone$ Command | ValidCard$ Instant.YouCtrl,Sorcery.YouCtrl | Execute$ RemoveEffect | Static$ True
SVar:RemoveEffect:DB$ ChangeZone | Origin$ Command | Destination$ Exile | Defined$ Self
Oracle:Flying, vigilance\nCeaseless Tempest — Whenever Storm deals combat damage to a player, the next instant or sorcery spell you cast this turn has storm. (When you cast it, copy it for each spell cast before it this turn. You may choose new targets for the copies.)
12 changes: 12 additions & 0 deletions forge-gui/res/cardsfolder/upcoming/wolverine_best_there_is.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Name:Wolverine, Best There Is
ManaCost:1 R G
Types:Legendary Creature Mutant Berserker Hero
PT:2/2
R:Event$ DamageDone | ActiveZones$ Battlefield | ValidSource$ Card.Self | ValidTarget$ Permanent,Player | ReplaceWith$ DmgTwice | Description$ Unrivaled Lethality — Double all damage NICKNAME would deal.
SVar:DmgTwice:DB$ ReplaceEffect | VarName$ DamageAmount | VarValue$ X
SVar:X:ReplaceCount$DamageAmount/Twice
T:Mode$ Phase | Phase$ End of Turn | TriggerZones$ Battlefield | CheckSVar$ Y | SVarCompare$ GE1 | Execute$ TrigPutCounter | TriggerDescription$ At the beginning of each end step, if NICKNAME dealt damage to another creature this turn, put a +1/+1 counter on him.
SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1
SVar:Y:Count$NumDamageThisTurn Card.Self Creature.Other
A:AB$ Regenerate | Cost$ 1 G | SpellDescription$ Regenerate NICKNAME. (The next time he would be destroyed this turn, instead tap him, remove him from combat, and heal all damage on him.)
Oracle:Unrivaled Lethality — Double all damage Wolverine would deal.\nAt the beginning of each end step, if Wolverine dealt damage to another creature this turn, put a +1/+1 counter on him.\n{1}{G}: Regenerate Wolverine. (The next time he would be destroyed this turn, instead tap him, remove him from combat, and heal all damage on him.)
1 change: 1 addition & 0 deletions forge-gui/res/lists/TypeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ Halfling:Halflings
Hamster:Hamsters
Harpy:Harpies
Hellion:Hellions
Hero:Heroes
Hippo:Hippos
Hippogriff:Hippogriffs
Homarid:Homarids
Expand Down
18 changes: 15 additions & 3 deletions forge-gui/src/main/java/forge/player/HumanCostDecision.java
Original file line number Diff line number Diff line change
Expand Up @@ -1330,9 +1330,20 @@ public PaymentDecision visit(final CostUntap cost) {

@Override
public PaymentDecision visit(final CostUnattach cost) {
final Card cardToUnattach = cost.findCardToUnattach(source, player, ability);
if (cardToUnattach != null && confirmAction(cost, Localizer.getInstance().getMessage("lblUnattachCardConfirm", CardTranslation.getTranslatedName(cardToUnattach.getName())))) {
return PaymentDecision.card(cardToUnattach);
final CardCollection cardToUnattach = cost.findCardToUnattach(source, player, ability);
if (cardToUnattach.size() == 1 && confirmAction(cost, Localizer.getInstance().getMessage("lblUnattachCardConfirm", CardTranslation.getTranslatedName(cardToUnattach.getFirst().getName())))) {
return PaymentDecision.card(cardToUnattach.getFirst());
}
if (cardToUnattach.size() > 1) {
int c = cost.getAbilityAmount(ability);
final InputSelectCardsFromList inp = new InputSelectCardsFromList(controller, c, c, cardToUnattach, ability);
inp.setCancelAllowed(true);
inp.setMessage(Localizer.getInstance().getMessage("lblUnattachCardConfirm", cost.getDescriptiveType()));
inp.showAndWait();
if (inp.hasCancelled() || inp.getSelected().size() != c) {
return null;
}
return PaymentDecision.card(inp.getSelected());
}
return null;
}
Expand All @@ -1341,6 +1352,7 @@ public PaymentDecision visit(final CostUnattach cost) {
public boolean paysRightAfterDecision() {
return true;
}

private boolean confirmAction(CostPart costPart, String message) {
CardView cardView = ability.getCardView();
if (GuiBase.getInterface().isLibgdxPort()) {
Expand Down

0 comments on commit 5a3f2ed

Please sign in to comment.