Merge pull request #2626 from tool4ever/fixnpe6

Fix Churning Reservoir NPE
This commit is contained in:
Anthony Calosa
2023-03-07 07:28:36 +08:00
committed by GitHub
11 changed files with 21 additions and 70 deletions

View File

@@ -358,7 +358,7 @@ public class DamageDealAi extends DamageAiBase {
return c.getSVar("Targeting").equals("Dies")
|| (ComputerUtilCombat.getEnoughDamageToKill(c, d, source, false, noPrevention) <= d)
&& !ComputerUtil.canRegenerate(ai, c)
&& !(c.getSVar("SacMe").length() > 0)
&& !c.hasSVar("SacMe")
&& !ComputerUtilCard.hasActiveUndyingOrPersist(c);
}
});
@@ -437,7 +437,7 @@ public class DamageDealAi extends DamageAiBase {
return c.getSVar("Targeting").equals("Dies")
|| (ComputerUtilCombat.getEnoughDamageToKill(c, d, source, false, noPrevention) <= d)
&& !ComputerUtil.canRegenerate(ai, c)
&& !(c.getSVar("SacMe").length() > 0);
&& !c.hasSVar("SacMe");
}
});

View File

@@ -1460,20 +1460,6 @@ public class AbilityUtils {
if (unlessCost.equals("CardManaCost")) {
cost = new Cost(source.getManaCost(), true);
}
else if (unlessCost.equals("TriggeredSpellManaCost")) {
SpellAbility triggered = (SpellAbility) sa.getRootAbility().getTriggeringObject(AbilityKey.SpellAbility);
Card triggeredCard = triggered.getHostCard();
if (triggeredCard.getManaCost() == null) {
cost = new Cost(ManaCost.ZERO, true);
} else {
int xCount = triggeredCard.getManaCost().countX();
int xPaid = triggeredCard.getXManaCostPaid() * xCount;
ManaCostBeingPaid toPay = new ManaCostBeingPaid(triggeredCard.getManaCost());
toPay.decreaseShard(ManaCostShard.X, xCount);
toPay.increaseGenericMana(xPaid);
cost = new Cost(toPay.toManaCost(), true);
}
}
else if (unlessCost.equals("ChosenManaCost")) {
if (!source.hasChosenCard()) {
cost = new Cost(ManaCost.ZERO, true);
@@ -2734,7 +2720,7 @@ public class AbilityUtils {
// Count$ThisTurnEntered <ZoneDestination> [from <ZoneOrigin>] <Valid>
if (sq[0].startsWith("ThisTurnEntered")) {
final String[] workingCopy = l[0].split("_");
final String[] workingCopy = l[0].split("_", 5);
ZoneType destination = ZoneType.smartValueOf(workingCopy[1]);
final boolean hasFrom = workingCopy[2].equals("from");
@@ -2747,7 +2733,7 @@ public class AbilityUtils {
// Count$LastTurnEntered <ZoneDestination> [from <ZoneOrigin>] <Valid>
if (sq[0].startsWith("LastTurnEntered")) {
final String[] workingCopy = l[0].split("_");
final String[] workingCopy = l[0].split("_", 5);
ZoneType destination = ZoneType.smartValueOf(workingCopy[1]);
final boolean hasFrom = workingCopy[2].equals("from");

View File

@@ -905,7 +905,7 @@ public abstract class SpellAbilityEffect {
return activator.getController().chooseSingleEntityForEffect(options, sa, Localizer.getInstance().getMessage("lblChoosePlayer"), null);
}
public void handleExiledWith(final Card movedCard, final SpellAbility cause) {
public static void handleExiledWith(final Card movedCard, final SpellAbility cause) {
Card exilingSource = cause.getHostCard();
// during replacement LKI might be used
if (cause.isReplacementAbility() && exilingSource.isLKI()) {

View File

@@ -1501,32 +1501,13 @@ public class CardProperty {
return false;
}
}
// syntax example: countersGE9 P1P1 or countersLT12TIME (greater number
// than 99 not supported)
/*
* slapshot5 - fair warning, you cannot use numbers with 2 digits
* (greater number than 9 not supported you can use X and the
* SVar:X:Number$12 to get two digits. This will need a better fix, and
* I have the beginnings of a regex below
*/
else if (property.startsWith("counters")) {
/*
* Pattern p = Pattern.compile("[a-z]*[A-Z][A-Z][X0-9]+.*$");
* String[] parse = ???
* System.out.println("Parsing completed of: "+Property); for (int i
* = 0; i < parse.length; i++) {
* System.out.println("parse["+i+"]: "+parse[i]); }
*/
// TODO get a working regex out of this pattern so the amount of
// digits doesn't matter
// syntax example: counters_GE9_P1P1 or counters_LT12_TIME
final String[] splitProperty = property.split("_");
final String strNum = splitProperty[1].substring(2);
final String comparator = splitProperty[1].substring(0, 2);
String counterType;
int number = AbilityUtils.calculateAmount(source, strNum, spellAbility);
counterType = splitProperty[2];
final String counterType = splitProperty[2];
final int number = AbilityUtils.calculateAmount(source, strNum, spellAbility);
final int actualnumber = card.getCounters(CounterType.getType(counterType));

View File

@@ -19,6 +19,7 @@ package forge.game.cost;
import forge.card.CardType;
import forge.game.Game;
import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card;
import forge.game.card.CardCollectionView;
import forge.game.card.CardLists;
@@ -187,11 +188,8 @@ public class CostExile extends CostPartWithList {
@Override
protected Card doPayment(SpellAbility ability, Card targetCard, final boolean effect) {
final Game game = targetCard.getGame();
final Card host = ability.getHostCard();
Card newCard = game.getAction().exile(targetCard, null);
host.addExiledCard(newCard);
newCard.setExiledWith(host);
newCard.setExiledBy(ability.getActivatingPlayer());
SpellAbilityEffect.handleExiledWith(newCard, ability);
return newCard;
}

View File

@@ -70,21 +70,11 @@ public class CostUnattach extends CostPartWithList {
*/
@Override
public final boolean canPay(final SpellAbility ability, final Player payer, final boolean effect) {
final Card source = ability.getHostCard();
final String type = this.getType();
if (type.equals("CARDNAME")) {
return source.isEquipping();
} else if (type.equals("OriginalHost")) {
Card originalEquipment = ability.getOriginalHost();
return originalEquipment.isEquipping();
} else {
return CardLists.getValidCards(source.getEquippedBy(), type, payer, source, ability).size() > 0;
}
return findCardToUnattach(ability.getHostCard(), payer, ability) != null;
}
public Card findCardToUnattach(final Card source, Player activator, SpellAbility ability) {
if (getType().equals("CARDNAME")) {
if (payCostFromSource()) {
if (source.isEquipping()) {
return source;
}

View File

@@ -503,8 +503,7 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
if (thisHasFizzled) { // Fizzle
if (sa.isBestow()) {
// 702.102d: if its target is illegal,
// the effect making it an Aura spell ends.
// 702.102e: if its target is illegal, the effect making it an Aura spell ends.
// It continues resolving as a creature spell.
source.unanimateBestow();
SpellAbility first = source.getFirstSpellAbility();
@@ -834,10 +833,9 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
}
if (activator.equals(activePlayer)) {
adjustAuraHost(sa);
activePlayerSAs.add(sa);
}
adjustAuraHost(sa);
}
simultaneousStackEntryList.removeAll(activePlayerSAs);

View File

@@ -5,9 +5,8 @@ PT:3/2
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Creature.YouCtrl+Other,Artifact.YouCtrl+Other | TriggerZones$ Battlefield | Execute$ TrigPutCounter | TriggerDescription$ Whenever another creature or artifact you control is put into a graveyard from the battlefield, put an oil counter on CARDNAME.
SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ OIL | CounterNum$ 1
T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigImmediateTrig | TriggerDescription$ Whenever CARDNAME attacks, you may remove two oil counters from it. When you do, target creature can't block this turn.
SVar:TrigImmediateTrig:AB$ ImmediateTrigger | Cost$ SubCounter<2/OIL> | SubAbility$ TrigPump | TriggerDescription$ When you do, target creature can't block this turn.
SVar:TrigImmediateTrig:AB$ ImmediateTrigger | Cost$ SubCounter<2/OIL> | Execute$ TrigPump | TriggerDescription$ When you do, target creature can't block this turn.
SVar:TrigPump:DB$ Pump | ValidTgts$ Creature | TgtPrompt$ Select target creature | IsCurse$ True | KW$ HIDDEN CARDNAME can't block.
SVar:X:Count$CardCounters.OIL
SVar:HasAttackEffect:TRUE
DeckHints:Ability$Counters
Oracle:Whenever another creature or artifact you control is put into a graveyard from the battlefield, put an oil counter on Forgehammer Centurion.\nWhenever Forgehammer Centurion attacks, you may remove two oil counters from it. When you do, target creature can't block this turn.

View File

@@ -379,8 +379,7 @@ public class HumanCostDecision extends CostDecisionMakerBase {
private PaymentDecision exileFromMiscZone(final CostExile cost, final SpellAbility sa, final int nNeeded, final CardCollection typeList) {
if (typeList.size() < nNeeded) { return null; }
final List<ZoneType> origin = Lists.newArrayList();
origin.add(cost.from);
final List<ZoneType> origin = Lists.newArrayList(cost.from);
final CardCollection exiled = new CardCollection();
final List<Card> chosen = controller.chooseCardsForZoneChange(ZoneType.Exile, origin, sa, typeList, mandatory ? nNeeded : 0,