mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 11:18:01 +00:00
Fix NPE with Mount Velus Manticore
This commit is contained in:
@@ -2239,7 +2239,7 @@ public class ComputerUtil {
|
|||||||
if (validString.contains("Creature") && !validString.contains("nonCreature")) {
|
if (validString.contains("Creature") && !validString.contains("nonCreature")) {
|
||||||
final Card c = ComputerUtilCard.getBestCreatureAI(goodChoices);
|
final Card c = ComputerUtilCard.getBestCreatureAI(goodChoices);
|
||||||
if (c != null) {
|
if (c != null) {
|
||||||
dChoices.add(ComputerUtilCard.getBestCreatureAI(goodChoices));
|
dChoices.add(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2764,7 +2764,8 @@ public class ComputerUtil {
|
|||||||
|| (type.is(CounterEnumType.TIME) && (!c.isInPlay() || "Chronozoa".equals(c.getName())))
|
|| (type.is(CounterEnumType.TIME) && (!c.isInPlay() || "Chronozoa".equals(c.getName())))
|
||||||
|| type.is(CounterEnumType.GOLD) || type.is(CounterEnumType.MUSIC) || type.is(CounterEnumType.PUPA)
|
|| type.is(CounterEnumType.GOLD) || type.is(CounterEnumType.MUSIC) || type.is(CounterEnumType.PUPA)
|
||||||
|| type.is(CounterEnumType.PARALYZATION) || type.is(CounterEnumType.SHELL) || type.is(CounterEnumType.SLEEP)
|
|| type.is(CounterEnumType.PARALYZATION) || type.is(CounterEnumType.SHELL) || type.is(CounterEnumType.SLEEP)
|
||||||
|| type.is(CounterEnumType.SLUMBER) || type.is(CounterEnumType.SLEIGHT) || type.is(CounterEnumType.WAGE);
|
|| type.is(CounterEnumType.SLUMBER) || type.is(CounterEnumType.SLEIGHT) || type.is(CounterEnumType.WAGE)
|
||||||
|
|| type.is(CounterEnumType.INCARNATION) || type.is(CounterEnumType.RUST);
|
||||||
}
|
}
|
||||||
|
|
||||||
// this countertypes has no effect
|
// this countertypes has no effect
|
||||||
@@ -2892,6 +2893,8 @@ public class ComputerUtil {
|
|||||||
public static boolean targetPlayableSpellCard(final Player ai, CardCollection options, final SpellAbility sa, final boolean withoutPayingManaCost, boolean mandatory) {
|
public static boolean targetPlayableSpellCard(final Player ai, CardCollection options, final SpellAbility sa, final boolean withoutPayingManaCost, boolean mandatory) {
|
||||||
// determine and target a card with a SA that the AI can afford and will play
|
// determine and target a card with a SA that the AI can afford and will play
|
||||||
AiController aic = ((PlayerControllerAi) ai.getController()).getAi();
|
AiController aic = ((PlayerControllerAi) ai.getController()).getAi();
|
||||||
|
sa.resetTargets();
|
||||||
|
|
||||||
CardCollection targets = new CardCollection();
|
CardCollection targets = new CardCollection();
|
||||||
for (Card c : options) {
|
for (Card c : options) {
|
||||||
if (withoutPayingManaCost && c.getManaCost() != null && c.getManaCost().countX() > 0) {
|
if (withoutPayingManaCost && c.getManaCost() != null && c.getManaCost().countX() > 0) {
|
||||||
@@ -2917,6 +2920,7 @@ public class ComputerUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targets.isEmpty()) {
|
if (targets.isEmpty()) {
|
||||||
if (mandatory && !options.isEmpty()) {
|
if (mandatory && !options.isEmpty()) {
|
||||||
targets = options;
|
targets = options;
|
||||||
@@ -2924,6 +2928,7 @@ public class ComputerUtil {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sa.getTargets().add(ComputerUtilCard.getBestAI(targets));
|
sa.getTargets().add(ComputerUtilCard.getBestAI(targets));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public class BecomesBlockedAi extends SpellAbilityAi {
|
|||||||
list = CardLists.getTargetableCards(list, sa);
|
list = CardLists.getTargetableCards(list, sa);
|
||||||
list = CardLists.getNotKeyword(list, Keyword.TRAMPLE);
|
list = CardLists.getNotKeyword(list, Keyword.TRAMPLE);
|
||||||
|
|
||||||
while (sa.getTargets().size() < tgt.getMaxTargets(source, sa)) {
|
while (sa.canAddMoreTarget()) {
|
||||||
Card choice = null;
|
Card choice = null;
|
||||||
|
|
||||||
if (list.isEmpty()) {
|
if (list.isEmpty()) {
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ public class ControlGainAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (sa.getTargets().size() < tgt.getMaxTargets(sa.getHostCard(), sa)) {
|
while (sa.canAddMoreTarget()) {
|
||||||
Card t = null;
|
Card t = null;
|
||||||
|
|
||||||
if (list.isEmpty()) {
|
if (list.isEmpty()) {
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ public class DebuffAi extends SpellAbilityAi {
|
|||||||
return mandatory && debuffMandatoryTarget(ai, sa, mandatory);
|
return mandatory && debuffMandatoryTarget(ai, sa, mandatory);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (sa.getTargets().size() < tgt.getMaxTargets(sa.getHostCard(), sa)) {
|
while (sa.canAddMoreTarget()) {
|
||||||
Card t = null;
|
Card t = null;
|
||||||
|
|
||||||
if (list.isEmpty()) {
|
if (list.isEmpty()) {
|
||||||
@@ -216,7 +216,7 @@ public class DebuffAi extends SpellAbilityAi {
|
|||||||
final CardCollection forced = CardLists.filterControlledBy(list, ai);
|
final CardCollection forced = CardLists.filterControlledBy(list, ai);
|
||||||
final Card source = sa.getHostCard();
|
final Card source = sa.getHostCard();
|
||||||
|
|
||||||
while (sa.getTargets().size() < tgt.getMaxTargets(source, sa)) {
|
while (sa.canAddMoreTarget()) {
|
||||||
if (pref.isEmpty()) {
|
if (pref.isEmpty()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -230,7 +230,7 @@ public class ProtectAi extends SpellAbilityAi {
|
|||||||
return mandatory && protectMandatoryTarget(ai, sa, mandatory);
|
return mandatory && protectMandatoryTarget(ai, sa, mandatory);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (sa.getTargets().size() < tgt.getMaxTargets(source, sa)) {
|
while (sa.canAddMoreTarget()) {
|
||||||
Card t = null;
|
Card t = null;
|
||||||
// boolean goodt = false;
|
// boolean goodt = false;
|
||||||
|
|
||||||
@@ -289,7 +289,7 @@ public class ProtectAi extends SpellAbilityAi {
|
|||||||
final List<Card> forced = CardLists.filterControlledBy(list, ai);
|
final List<Card> forced = CardLists.filterControlledBy(list, ai);
|
||||||
final Card source = sa.getHostCard();
|
final Card source = sa.getHostCard();
|
||||||
|
|
||||||
while (sa.getTargets().size() < tgt.getMaxTargets(source, sa)) {
|
while (sa.canAddMoreTarget()) {
|
||||||
if (pref.isEmpty()) {
|
if (pref.isEmpty()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -306,7 +306,7 @@ public class ProtectAi extends SpellAbilityAi {
|
|||||||
sa.getTargets().add(c);
|
sa.getTargets().add(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (sa.getTargets().size() < tgt.getMaxTargets(source, sa)) {
|
while (sa.canAddMoreTarget()) {
|
||||||
if (pref2.isEmpty()) {
|
if (pref2.isEmpty()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -437,7 +437,7 @@ public class PumpAi extends PumpAiBase {
|
|||||||
&& !(sa.isCurse() && defense < 0)
|
&& !(sa.isCurse() && defense < 0)
|
||||||
&& !containsNonCombatKeyword(keywords)
|
&& !containsNonCombatKeyword(keywords)
|
||||||
&& !"UntilYourNextTurn".equals(sa.getParam("Duration"))
|
&& !"UntilYourNextTurn".equals(sa.getParam("Duration"))
|
||||||
&& !"Snapcaster".equals(sa.getParam("AILogic"))
|
&& !"ReplaySpell".equals(sa.getParam("AILogic"))
|
||||||
&& !isFight) {
|
&& !isFight) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -595,8 +595,8 @@ public class PumpAi extends PumpAiBase {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("Snapcaster".equals(sa.getParam("AILogic"))) {
|
if ("ReplaySpell".equals(sa.getParam("AILogic"))) {
|
||||||
if (!ComputerUtil.targetPlayableSpellCard(ai, list, sa, false, false)) {
|
if (!ComputerUtil.targetPlayableSpellCard(ai, list, sa, false, mandatory)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -662,7 +662,7 @@ public class PumpAi extends PumpAiBase {
|
|||||||
forced = CardLists.filterControlledBy(list, ai.getOpponents());
|
forced = CardLists.filterControlledBy(list, ai.getOpponents());
|
||||||
}
|
}
|
||||||
|
|
||||||
while (sa.getTargets().size() < tgt.getMaxTargets(source, sa)) {
|
while (sa.canAddMoreTarget()) {
|
||||||
if (pref.isEmpty()) {
|
if (pref.isEmpty()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ public class TwoPilesAi extends SpellAbilityAi {
|
|||||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||||
if (tgt != null) {
|
if (tgt != null) {
|
||||||
sa.resetTargets();
|
sa.resetTargets();
|
||||||
if (tgt.canTgtPlayer()) {
|
if (sa.canTarget(opp)) {
|
||||||
sa.getTargets().add(opp);
|
sa.getTargets().add(opp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -239,8 +239,7 @@ public class UntapAi extends SpellAbilityAi {
|
|||||||
tgt.getValidTgts(), source.getController(), source, sa);
|
tgt.getValidTgts(), source.getController(), source, sa);
|
||||||
list = CardLists.getTargetableCards(list, sa);
|
list = CardLists.getTargetableCards(list, sa);
|
||||||
|
|
||||||
// filter by enchantments and planeswalkers, their tapped state doesn't
|
// filter by enchantments and planeswalkers, their tapped state doesn't matter.
|
||||||
// matter.
|
|
||||||
final String[] tappablePermanents = { "Enchantment", "Planeswalker" };
|
final String[] tappablePermanents = { "Enchantment", "Planeswalker" };
|
||||||
CardCollection tapList = CardLists.getValidCards(list, tappablePermanents, source.getController(), source, sa);
|
CardCollection tapList = CardLists.getValidCards(list, tappablePermanents, source.getController(), source, sa);
|
||||||
|
|
||||||
@@ -271,7 +270,7 @@ public class UntapAi extends SpellAbilityAi {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (sa.getTargets().size() < tgt.getMaxTargets(source, sa)) {
|
while (sa.canAddMoreTarget()) {
|
||||||
Card choice = null;
|
Card choice = null;
|
||||||
|
|
||||||
if (tapList.isEmpty()) {
|
if (tapList.isEmpty()) {
|
||||||
|
|||||||
@@ -2040,7 +2040,7 @@ public class AbilityUtils {
|
|||||||
} else {
|
} else {
|
||||||
ce = c;
|
ce = c;
|
||||||
}
|
}
|
||||||
return doXMath(getNumberOfTypes(ce), expr, c, ctb);
|
return doXMath(ce == null ? 0 : getNumberOfTypes(ce), expr, c, ctb);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sq[0].contains("CardNumColors")) {
|
if (sq[0].contains("CardNumColors")) {
|
||||||
|
|||||||
@@ -401,8 +401,7 @@ public final class CMatchUI
|
|||||||
selectedDocBeforeCombat = combatDoc.getParentCell().getSelected();
|
selectedDocBeforeCombat = combatDoc.getParentCell().getSelected();
|
||||||
if (selectedDocBeforeCombat != combatDoc) {
|
if (selectedDocBeforeCombat != combatDoc) {
|
||||||
SDisplayUtil.showTab(combatDoc);
|
SDisplayUtil.showTab(combatDoc);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
selectedDocBeforeCombat = null; //don't need to cache combat doc this way
|
selectedDocBeforeCombat = null; //don't need to cache combat doc this way
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -744,8 +743,6 @@ public final class CMatchUI
|
|||||||
//else if (toFocus == btn1)
|
//else if (toFocus == btn1)
|
||||||
//btn2.setFocusable(false);
|
//btn2.setFocusable(false);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
final Runnable focusRoutine = new Runnable() {
|
final Runnable focusRoutine = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public final void run() {
|
public final void run() {
|
||||||
@@ -1364,7 +1361,6 @@ public final class CMatchUI
|
|||||||
}
|
}
|
||||||
// In any case, I have to increase the counter
|
// In any case, I have to increase the counter
|
||||||
nextNotifiableStackIndex++;
|
nextNotifiableStackIndex++;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Not yet time to show the modal - schedule the method again, and try again later
|
// Not yet time to show the modal - schedule the method again, and try again later
|
||||||
Runnable tryAgainThread = new Runnable() {
|
Runnable tryAgainThread = new Runnable() {
|
||||||
|
|||||||
@@ -4,6 +4,6 @@ Types:Creature Human Wizard
|
|||||||
PT:2/1
|
PT:2/1
|
||||||
K:Flash
|
K:Flash
|
||||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigRearrange | TriggerDescription$ When CARDNAME enters the battlefield, target instant or sorcery card in your graveyard gains flashback until end of turn. The flashback cost is equal to its mana cost. (You may cast that card from your graveyard for its flashback cost. Then exile it.)
|
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigRearrange | TriggerDescription$ When CARDNAME enters the battlefield, target instant or sorcery card in your graveyard gains flashback until end of turn. The flashback cost is equal to its mana cost. (You may cast that card from your graveyard for its flashback cost. Then exile it.)
|
||||||
SVar:TrigRearrange:DB$ Pump | ValidTgts$ Instant.YouCtrl,Sorcery.YouCtrl | TgtZone$ Graveyard | TgtPrompt$ Select target instant or sorcery card | KW$ Flashback | PumpZone$ Graveyard | AILogic$ Snapcaster
|
SVar:TrigRearrange:DB$ Pump | ValidTgts$ Instant.YouCtrl,Sorcery.YouCtrl | TgtZone$ Graveyard | TgtPrompt$ Select target instant or sorcery card | KW$ Flashback | PumpZone$ Graveyard | AILogic$ ReplaySpell
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/snapcaster_mage.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/snapcaster_mage.jpg
|
||||||
Oracle:Flash\nWhen Snapcaster Mage enters the battlefield, target instant or sorcery card in your graveyard gains flashback until end of turn. The flashback cost is equal to its mana cost. (You may cast that card from your graveyard for its flashback cost. Then exile it.)
|
Oracle:Flash\nWhen Snapcaster Mage enters the battlefield, target instant or sorcery card in your graveyard gains flashback until end of turn. The flashback cost is equal to its mana cost. (You may cast that card from your graveyard for its flashback cost. Then exile it.)
|
||||||
|
|||||||
Reference in New Issue
Block a user