mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 03:38:01 +00:00
Merge branch 'fixes' into 'master'
Small fixes Closes #1891 and #1890 See merge request core-developers/forge!4885
This commit is contained in:
@@ -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")) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user