Merge branch 'fixes' into 'master'

Small fixes

Closes #1891 and #1890

See merge request core-developers/forge!4885
This commit is contained in:
Michael Kamensky
2021-06-15 17:45:13 +00:00
18 changed files with 47 additions and 33 deletions

View File

@@ -68,7 +68,6 @@ import forge.util.Aggregates;
public class ControlGainAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(final Player ai, final SpellAbility sa) {
final List<String> lose = Lists.newArrayList();
if (sa.hasParam("LoseControl")) {

View File

@@ -39,6 +39,7 @@ import forge.game.keyword.Keyword;
import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.player.PlayerCollection;
import forge.game.spellability.AbilitySub;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetChoices;
@@ -844,7 +845,7 @@ public class DamageDealAi extends DamageAiBase {
// this is for Triggered targets that are mandatory
final boolean noPrevention = sa.hasParam("NoPrevention");
final boolean divided = sa.isDividedAsYouChoose();
final Player opp = ai.getWeakestOpponent();
PlayerCollection opps = ai.getOpponents();
while (sa.canAddMoreTarget()) {
if (tgt.canTgtPlaneswalker()) {
@@ -872,13 +873,17 @@ public class DamageDealAi extends DamageAiBase {
}
}
if (sa.canTarget(opp)) {
if (sa.getTargets().add(opp)) {
if (divided) {
sa.addDividedAllocation(opp, dmg);
break;
if (!opps.isEmpty()) {
Player opp = opps.getFirst();
opps.remove(opp);
if (sa.canTarget(opp)) {
if (sa.getTargets().add(opp)) {
if (divided) {
sa.addDividedAllocation(opp, dmg);
break;
}
continue;
}
continue;
}
}

View File

@@ -1,5 +1,6 @@
package forge.ai.ability;
import forge.ai.AiAttackController;
import forge.ai.SpellAbilityAi;
import forge.game.player.Player;
import forge.game.player.PlayerActionConfirmMode;
@@ -8,16 +9,33 @@ import forge.game.spellability.SpellAbility;
public class SkipPhaseAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
return true;
return targetPlayer(aiPlayer, sa, false);
}
@Override
protected boolean doTriggerAINoCost(Player aiPlayer, SpellAbility sa, boolean mandatory) {
return mandatory || canPlayAI(aiPlayer, sa);
return targetPlayer(aiPlayer, sa, mandatory);
}
@Override
public boolean confirmAction(Player player, SpellAbility sa, PlayerActionConfirmMode mode, String message) {
return true;
}
public boolean targetPlayer(Player ai, SpellAbility sa, boolean mandatory) {
if (sa.usesTargeting()) {
final Player opp = AiAttackController.choosePreferredDefenderPlayer(ai);
sa.resetTargets();
if (sa.canTarget(opp)) {
sa.getTargets().add(opp);
}
else if (mandatory && sa.canTarget(ai)) {
sa.getTargets().add(ai);
}
else {
return false;
}
}
return true;
}
}

View File

@@ -1,6 +1,5 @@
package forge.ai.ability;
import forge.ai.SpellAbilityAi;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;

View File

@@ -2731,7 +2731,6 @@ public class AbilityUtils {
return doXMath(powers.size(), expr, c, ctb);
}
if (sq[0].startsWith("MostProminentCreatureType")) {
String restriction = l[0].split(" ")[1];
CardCollection list = CardLists.getValidCards(game.getCardsIn(ZoneType.Battlefield), restriction, player, c, ctb);

View File

@@ -291,7 +291,6 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
* @return a {@link java.lang.String} object.
*/
private static String changeKnownOriginStackDescription(final SpellAbility sa) {
final StringBuilder sb = new StringBuilder();
final Card host = sa.getHostCard();
@@ -1047,7 +1046,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
// only multi-select if player can select more than one
if (changeNum > 1 && allowMultiSelect(decider, sa)) {
List<Card> selectedCards;
if (! sa.hasParam("SelectPrompt")) {
if (!sa.hasParam("SelectPrompt")) {
// new default messaging for multi select
if (fetchList.size() > changeNum) {
//Select up to %changeNum cards from %players %origin

View File

@@ -58,8 +58,8 @@ public class ImmediateTriggerEffect extends SpellAbilityEffect {
Card lki = CardUtil.getLKICopy(gameCard);
lki.clearControllers();
lki.setOwner(sa.getActivatingPlayer());
// if this trigger is part of ETBReplacement it shouldn't run with LKI from incomplete zone change (Wall of Stolen Identity)
final Card trigHost = sa.getRootAbility().getReplacementEffect() != null && sa.getRootAbility().getReplacementEffect().getMode().equals(ReplacementType.Moved) ? gameCard : lki;
// if this trigger is part of ETBReplacement it shouldn't run with LKI from incomplete zone change (Mimic Vat + Wall of Stolen Identity)
final Card trigHost = sa.getRootAbility().getReplacementEffect() != null && sa.getRootAbility().getReplacementEffect().getMode().equals(ReplacementType.Moved) && gameCard.getZone() == null ? gameCard : lki;
final Trigger immediateTrig = TriggerHandler.parseTrigger(mapParams, trigHost, sa.isIntrinsic(), null);
immediateTrig.setSpawningAbility(sa.copy(lki, sa.getActivatingPlayer(), true));

View File

@@ -275,7 +275,7 @@ public final class CardUtil {
newCopy.addRemembered(in.getRemembered());
newCopy.addImprintedCards(in.getImprintedCards());
for(Table.Cell<Player, CounterType, Integer> cl : in.getEtbCounters()) {
for (Table.Cell<Player, CounterType, Integer> cl : in.getEtbCounters()) {
newCopy.addEtbCounter(cl.getColumnKey(), cl.getValue(), cl.getRowKey());
}

View File

@@ -112,13 +112,11 @@ public class CostPartMana extends CostPart {
@Override
public boolean isUndoable() { return true; }
@Override
public final String toString() {
return cost.toString();
}
@Override
public final boolean canPay(final SpellAbility ability, final Player payer) {
// For now, this will always return true. But this should probably be

View File

@@ -6,7 +6,7 @@ K:Double Strike
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigChangeZone | TriggerDescription$ When CARDNAME enters the battlefield, each player puts a creature card with mana value 3 or less from their graveyard onto the battlefield.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigSac | ManaNotSpent$ R | TriggerDescription$ When CARDNAME enters the battlefield, sacrifice it unless {R} was spent to cast it.
SVar:TrigChangeZone:DB$ RepeatEach | RepeatPlayers$ Player | RepeatSubAbility$ DBChangeZone
SVar:DBChangeZone:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ChangeType$ Creature.RememberedPlayerCtrl+cmcLE3 | ChangeNum$ 1 | Hidden$ True | DefinedPlayer$ Player.IsRemembered | Chooser$ Player.IsRemembered
SVar:DBChangeZone:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ChangeType$ Creature.RememberedPlayerCtrl+cmcLE3 | ChangeNum$ 1 | Hidden$ True | DefinedPlayer$ Player.IsRemembered | Chooser$ Player.IsRemembered | Mandatory$ True
SVar:TrigSac:DB$ Sacrifice | Defined$ Self
SVar:ManaNeededToAvoidNegativeEffect:red
SVar:Picture:http://www.wizards.com/global/images/magic/general/crypt_champion.jpg

View File

@@ -2,7 +2,7 @@ Name:Exhume
ManaCost:1 B
Types:Sorcery
A:SP$ RepeatEach | Cost$ 1 B | RepeatSubAbility$ DBChangeZone | RepeatPlayers$ Player | SpellDescription$ Each player puts a creature card from their graveyard onto the battlefield.
SVar:DBChangeZone:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ChangeType$ Creature.RememberedPlayerCtrl | DefinedPlayer$ Player.IsRemembered | Chooser$ Player.IsRemembered | ChangeNum$ 1 | Hidden$ True
SVar:DBChangeZone:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ChangeType$ Creature.RememberedPlayerCtrl | DefinedPlayer$ Player.IsRemembered | Chooser$ Player.IsRemembered | ChangeNum$ 1 | Hidden$ True | Mandatory$ True
SVar:X:Count$TypeInYourYard.Creature
SVar:NeedsToPlayVar:X GE1
SVar:Picture:http://www.wizards.com/global/images/magic/general/exhume.jpg

View File

@@ -7,8 +7,8 @@ SVar:DBRepeat:DB$ RepeatEach | RepeatPlayers$ ChosenAndYou | RepeatSubAbility$ D
SVar:DBDraw:DB$ Draw | Defined$ Player.IsRemembered | NumCards$ 2 | ConditionCheckSVar$ X | ConditionSVarCompare$ GE1
SVar:X:RememberedLKI$Valid Creature.RememberedPlayerCtrl
SVar:DBChoose:DB$ ChoosePlayer | Defined$ You | Choices$ Player.Opponent | SubAbility$ DBReturnYou
SVar:DBReturnYou:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ChangeType$ Creature.YouCtrl | ChangeNum$ 1 | Hidden$ True | SubAbility$ DBReturnOpp
SVar:DBReturnOpp:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ChangeType$ Creature.ChosenCtrl | DefinedPlayer$ ChosenPlayer | Chooser$ ChosenPlayer | ChangeNum$ 1 | Hidden$ True | SubAbility$ DBCleanup
SVar:DBReturnYou:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ChangeType$ Creature.YouCtrl | ChangeNum$ 1 | Hidden$ True | Mandatory$ True | SubAbility$ DBReturnOpp
SVar:DBReturnOpp:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ChangeType$ Creature.ChosenCtrl | DefinedPlayer$ ChosenPlayer | Chooser$ ChosenPlayer | ChangeNum$ 1 | Hidden$ True | Mandatory$ True | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
AI:RemoveDeck:All
AI:RemoveDeck:Random

View File

@@ -6,7 +6,6 @@ SVar:DBDigUntil:DB$ DigUntil | Amount$ X | ConditionCheckSVar$ X | ConditionSVar
SVar:DBShuffle:DB$ Shuffle | Defined$ You
SVar:X:Count$Valid Creature.ChosenType+YouCtrl
AI:RemoveDeck:Random
#TODO: This could benefit from something like "Creature.YouCtrl+sharesCreatureTypeWithAnotherCreature" (doesn't exist in code yet)
SVar:NeedsToPlay:Creature.YouCtrl+inZoneBattlefield
SVar:Picture:http://www.wizards.com/global/images/magic/general/kindred_summons.jpg
SVar:NeedsToPlayVar:MaxTypes GE2
SVar:MaxTypes:Count$MostProminentCreatureType Creature.YouCtrl
Oracle:Choose a creature type. Reveal cards from the top of your library until you reveal X creature cards of the chosen type, where X is the number of creatures you control of that type. Put those cards onto the battlefield, then shuffle the rest of the revealed cards into your library.

View File

@@ -4,7 +4,7 @@ Types:Enchantment
A:AB$ ChooseSource | Cost$ Sac<1/Creature> | Choices$ Card,Emblem | AILogic$ NeedsPrevention | SubAbility$ DBEffect | SpellDescription$ The next time a source of your choice would deal damage to any target this turn, prevent that damage.
SVar:DBEffect:DB$ Effect | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target to prevent damage to | Triggers$ OutOfSight | ReplacementEffects$ RPreventNextFromSource | RememberObjects$ Targeted | SubAbility$ DBCleanup | ConditionDefined$ ChosenCard | ConditionPresent$ Card,Emblem | ConditionCompare$ GE1
SVar:OutOfSight:Mode$ ChangesZone | TriggerZones$ Command | Origin$ Battlefield | Destination$ Any | ValidCard$ Card.IsRemembered | Execute$ ExileEffect | Static$ True
SVar:RPreventNextFromSource:Event$ DamageDone | ValidSource$ Card.ChosenCard,Emblem.ChosenCard | ValidTarget$ Card.IsRemembered,Player.IsRemembered | ReplaceWith$ ExileEffect | PreventionEffect$ True | Description$ The next time the chosen source deals damage to the any target, prevent that damage.
SVar:RPreventNextFromSource:Event$ DamageDone | ValidSource$ Card.ChosenCard,Emblem.ChosenCard | ValidTarget$ Card.IsRemembered,Player.IsRemembered | ReplaceWith$ ExileEffect | PreventionEffect$ True | Description$ The next time the chosen source deals damage to the target, prevent that damage.
SVar:ExileEffect:DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile
SVar:DBCleanup:DB$ Cleanup | ClearChosenCard$ True
AI:RemoveDeck:All

View File

@@ -6,7 +6,7 @@ T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | Execute$ TrigLandship | Trigg
SVar:TrigLandship:DB$ PeekAndReveal | PeekAmount$ 1 | RevealValid$ Land | RevealOptional$ True | RememberRevealed$ True | SubAbility$ DBToken
SVar:DBToken:DB$ Token | TokenScript$ g_1_1_elf_warrior | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ EQ1 | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.sharesCreatureTypeWith | TriggerZones$ Battlefield | Execute$ TrigPumpAll | TriggerDescription$ Kinfall — Whenever a creature enters the battlefield under your control, if it shares a creature type with Plane-Merge Elf, creatures you control get +1/+1 until end of turn.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.YouCtrl+sharesCreatureTypeWith | TriggerZones$ Battlefield | Execute$ TrigPumpAll | TriggerDescription$ Kinfall — Whenever a creature enters the battlefield under your control, if it shares a creature type with Plane-Merge Elf, creatures you control get +1/+1 until end of turn.
SVar:TrigPumpAll:DB$ PumpAll | ValidCards$ Creature.YouCtrl | NumAtt$ +1 | NumDef$ +1 | ConditionDefined$ TriggeredCard | ConditionPresent$ Card.sharesCreatureTypeWith
DeckHas:Ability$Token
Oracle:Landship — At the beginning of your upkeep, you may look at the top card of your library. If it's a land, you may reveal it. If you do, create a 1/1 green Elf Warrior creature token.\nKinfall — Whenever a creature enters the battlefield under your control, if it shares a creature type with Plane-Merge Elf, creatures you control get +1/+1 until end of turn.

View File

@@ -2,7 +2,6 @@ Name:Sigil Captain
ManaCost:1 G W W
Types:Creature Rhino Soldier
PT:3/3
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.powerEQ1+toughnessEQ1+Other+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigPutCounter | TriggerDescription$ Whenever a creature enters the battlefield under your control, if that creature is 1/1, put two +1/+1 counters on it.
SVar:TrigPutCounter:DB$ PutCounter | Defined$ TriggeredCardLKICopy | CounterType$ P1P1 | CounterNum$ 2
SVar:Picture:http://www.wizards.com/global/images/magic/general/sigil_captain.jpg
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.powerEQ1+toughnessEQ1+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigPutCounter | TriggerDescription$ Whenever a creature enters the battlefield under your control, if that creature is 1/1, put two +1/+1 counters on it.
SVar:TrigPutCounter:DB$ PutCounter | Defined$ TriggeredCardLKICopy | CounterType$ P1P1 | CounterNum$ 2 | ConditionDefined$ TriggeredCard | ConditionPresent$ Card.powerEQ1+toughnessEQ1
Oracle:Whenever a creature enters the battlefield under your control, if that creature is 1/1, put two +1/+1 counters on it.

View File

@@ -271,7 +271,7 @@ public abstract class InputPayMana extends InputSyncronizedBase {
}
// Store some information about color costs to help with any mana choices
if (colorNeeded == 0) { // only colorless left
if (colorNeeded == 0) { // only colorless left
if (saPaidFor.getHostCard() != null && saPaidFor.getHostCard().hasSVar("ManaNeededToAvoidNegativeEffect")) {
String[] negEffects = saPaidFor.getHostCard().getSVar("ManaNeededToAvoidNegativeEffect").split(",");
for (String negColor : negEffects) {

View File

@@ -72,7 +72,6 @@ public class InputPayManaOfCostPayment extends InputPayMana {
msg.append(messagePrefix).append("\n");
}
if (FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_DETAILED_SPELLDESC_IN_PROMPT)) {
// msg.append(saPaidFor.getStackDescription().replace("(Targeting ERROR)", ""));
if (saPaidFor.isSpell()) {
msg.append(saPaidFor.getStackDescription().replace("(Targeting ERROR)", "")).append("\n\n");
} else {