Fix NPE with Mount Velus Manticore

This commit is contained in:
tool4EvEr
2021-10-14 13:26:31 +02:00
parent 1617c433d0
commit 3b86f4f0c2
11 changed files with 26 additions and 26 deletions

View File

@@ -2239,7 +2239,7 @@ public class ComputerUtil {
if (validString.contains("Creature") && !validString.contains("nonCreature")) {
final Card c = ComputerUtilCard.getBestCreatureAI(goodChoices);
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.GOLD) || type.is(CounterEnumType.MUSIC) || type.is(CounterEnumType.PUPA)
|| 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
@@ -2892,6 +2893,8 @@ public class ComputerUtil {
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
AiController aic = ((PlayerControllerAi) ai.getController()).getAi();
sa.resetTargets();
CardCollection targets = new CardCollection();
for (Card c : options) {
if (withoutPayingManaCost && c.getManaCost() != null && c.getManaCost().countX() > 0) {
@@ -2917,6 +2920,7 @@ public class ComputerUtil {
}
}
}
if (targets.isEmpty()) {
if (mandatory && !options.isEmpty()) {
targets = options;
@@ -2924,6 +2928,7 @@ public class ComputerUtil {
return false;
}
}
sa.getTargets().add(ComputerUtilCard.getBestAI(targets));
return true;
}

View File

@@ -33,7 +33,7 @@ public class BecomesBlockedAi extends SpellAbilityAi {
list = CardLists.getTargetableCards(list, sa);
list = CardLists.getNotKeyword(list, Keyword.TRAMPLE);
while (sa.getTargets().size() < tgt.getMaxTargets(source, sa)) {
while (sa.canAddMoreTarget()) {
Card choice = null;
if (list.isEmpty()) {

View File

@@ -196,7 +196,7 @@ public class ControlGainAi extends SpellAbilityAi {
}
}
while (sa.getTargets().size() < tgt.getMaxTargets(sa.getHostCard(), sa)) {
while (sa.canAddMoreTarget()) {
Card t = null;
if (list.isEmpty()) {

View File

@@ -136,7 +136,7 @@ public class DebuffAi extends SpellAbilityAi {
return mandatory && debuffMandatoryTarget(ai, sa, mandatory);
}
while (sa.getTargets().size() < tgt.getMaxTargets(sa.getHostCard(), sa)) {
while (sa.canAddMoreTarget()) {
Card t = null;
if (list.isEmpty()) {
@@ -216,7 +216,7 @@ public class DebuffAi extends SpellAbilityAi {
final CardCollection forced = CardLists.filterControlledBy(list, ai);
final Card source = sa.getHostCard();
while (sa.getTargets().size() < tgt.getMaxTargets(source, sa)) {
while (sa.canAddMoreTarget()) {
if (pref.isEmpty()) {
break;
}

View File

@@ -230,7 +230,7 @@ public class ProtectAi extends SpellAbilityAi {
return mandatory && protectMandatoryTarget(ai, sa, mandatory);
}
while (sa.getTargets().size() < tgt.getMaxTargets(source, sa)) {
while (sa.canAddMoreTarget()) {
Card t = null;
// boolean goodt = false;
@@ -289,7 +289,7 @@ public class ProtectAi extends SpellAbilityAi {
final List<Card> forced = CardLists.filterControlledBy(list, ai);
final Card source = sa.getHostCard();
while (sa.getTargets().size() < tgt.getMaxTargets(source, sa)) {
while (sa.canAddMoreTarget()) {
if (pref.isEmpty()) {
break;
}
@@ -306,7 +306,7 @@ public class ProtectAi extends SpellAbilityAi {
sa.getTargets().add(c);
}
while (sa.getTargets().size() < tgt.getMaxTargets(source, sa)) {
while (sa.canAddMoreTarget()) {
if (pref2.isEmpty()) {
break;
}

View File

@@ -437,7 +437,7 @@ public class PumpAi extends PumpAiBase {
&& !(sa.isCurse() && defense < 0)
&& !containsNonCombatKeyword(keywords)
&& !"UntilYourNextTurn".equals(sa.getParam("Duration"))
&& !"Snapcaster".equals(sa.getParam("AILogic"))
&& !"ReplaySpell".equals(sa.getParam("AILogic"))
&& !isFight) {
return false;
}
@@ -595,8 +595,8 @@ public class PumpAi extends PumpAiBase {
});
}
if ("Snapcaster".equals(sa.getParam("AILogic"))) {
if (!ComputerUtil.targetPlayableSpellCard(ai, list, sa, false, false)) {
if ("ReplaySpell".equals(sa.getParam("AILogic"))) {
if (!ComputerUtil.targetPlayableSpellCard(ai, list, sa, false, mandatory)) {
return false;
}
}
@@ -662,7 +662,7 @@ public class PumpAi extends PumpAiBase {
forced = CardLists.filterControlledBy(list, ai.getOpponents());
}
while (sa.getTargets().size() < tgt.getMaxTargets(source, sa)) {
while (sa.canAddMoreTarget()) {
if (pref.isEmpty()) {
break;
}

View File

@@ -34,7 +34,7 @@ public class TwoPilesAi extends SpellAbilityAi {
final TargetRestrictions tgt = sa.getTargetRestrictions();
if (tgt != null) {
sa.resetTargets();
if (tgt.canTgtPlayer()) {
if (sa.canTarget(opp)) {
sa.getTargets().add(opp);
}
}

View File

@@ -239,8 +239,7 @@ public class UntapAi extends SpellAbilityAi {
tgt.getValidTgts(), source.getController(), source, sa);
list = CardLists.getTargetableCards(list, sa);
// filter by enchantments and planeswalkers, their tapped state doesn't
// matter.
// filter by enchantments and planeswalkers, their tapped state doesn't matter.
final String[] tappablePermanents = { "Enchantment", "Planeswalker" };
CardCollection tapList = CardLists.getValidCards(list, tappablePermanents, source.getController(), source, sa);
@@ -271,7 +270,7 @@ public class UntapAi extends SpellAbilityAi {
return false;
}
while (sa.getTargets().size() < tgt.getMaxTargets(source, sa)) {
while (sa.canAddMoreTarget()) {
Card choice = null;
if (tapList.isEmpty()) {

View File

@@ -2040,7 +2040,7 @@ public class AbilityUtils {
} else {
ce = c;
}
return doXMath(getNumberOfTypes(ce), expr, c, ctb);
return doXMath(ce == null ? 0 : getNumberOfTypes(ce), expr, c, ctb);
}
if (sq[0].contains("CardNumColors")) {

View File

@@ -401,8 +401,7 @@ public final class CMatchUI
selectedDocBeforeCombat = combatDoc.getParentCell().getSelected();
if (selectedDocBeforeCombat != combatDoc) {
SDisplayUtil.showTab(combatDoc);
}
else {
} else {
selectedDocBeforeCombat = null; //don't need to cache combat doc this way
}
}
@@ -744,8 +743,6 @@ public final class CMatchUI
//else if (toFocus == btn1)
//btn2.setFocusable(false);
final Runnable focusRoutine = new Runnable() {
@Override
public final void run() {
@@ -1364,7 +1361,6 @@ public final class CMatchUI
}
// In any case, I have to increase the counter
nextNotifiableStackIndex++;
} else {
// Not yet time to show the modal - schedule the method again, and try again later
Runnable tryAgainThread = new Runnable() {

View File

@@ -4,6 +4,6 @@ Types:Creature Human Wizard
PT:2/1
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.)
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
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.)